PDA

View Full Version : *.csv oder *.txt mit einer Datensatz-Größe von mehr als 32 MB



Seiten : [1] 2

votch
27-01-20, 09:47
Hallo zusammen,

gibt es eine Möglichkeit, Files mit einer Größe von über 32 MB (z.b. *.csv oder *.txt) zu verarbeiten.

Die Files liegen im IFS, aber egal ob ich die Dateien mit fgets verarbeite oder eine Immport-Datei definieren möchte, stoße ich auf eine Grenze von ~32MB.

Vorab schon mal Danke.

KingofKning
27-01-20, 11:17
Poste doch mal Dein Programm. Kann eigentlich nicht sein das es ein 32 MB Limit gibt.....

GG 4142

TheDevil
27-01-20, 12:42
Kenn nun nicht die maximale Größe eines Feldes aber ...
Besteht der Fileinhalt vielleicht aus einem einzigen Feld (kein linefeed, crlf ...) ?

votch
27-01-20, 17:34
Hallo, das Thema hat sich vermutlich erledigt.

Ich sag nur, wenn man mal schnell was mit PDM machen will und zu blöd zum Lesen ist... :-(

Es ging um die Datensatz-Länge von 32 KB, da ich bei Erstellung einer PF diese Nachricht bekam:
* CPD7925 30 590 Nachricht . . . : Satzlänge überschreitet 32.766 Byte.

und mir beim Editieren des Programms, bei der Definition...
D fgets PR * EXTPROC('_C_IFS_fgets')
D dta 32767A options(*varsize)
D size 10I 0 value
D file * OPTIONS(*STRING) value

eine maximale Länge von 1-32767 angezeigt wurde

Bei der Definition eines Feldes via RDi sieht das aber wesentlich besser aus...
dcl-S String varchar(1212121212);
RNF0501E Länge des Zeicheneintrags überschreitet 16773104; für die Länge wird standardmäßig 16773104 angenommen.

Fuerchau
28-01-20, 09:02
Trotzdem verwechselst du da was.
"dcl-s String" ist eine Single-Variable während "dta" ein Prozedurparameter ist.
Und "options(*varsize)" entspricht nicht "varchar".
*varsize = Parameter per reference aber beliebiger Länge, die Länge wird nicht übergeben.
varchar = Feld mit einer 2/4-Byte Längeninformation vorneweg

Die klassische Definition im RPGLE erlaubt hier bis 7 Stellen, also knapp 10MB, ich habe 99.999.999 ausprobiert (also 99999999A) ohne Fehler.
Die Free-Definition erlaubt da dann eben die klassische Grenze von knapp 16MB.

votch
28-01-20, 19:36
@all, danke für die Antworten

@fuerchau, auch Dir Danke für die Antwort, Du hast natürlich vollkommen Recht.
Mir ging es bei der Feld-Definition im RDi auch eigentlich nur um die Meldung von RDi bzgl. der maximalen Feldlänge, völlig unabhängig von der alten Prozedur bzw. den Prozedur-Parametern. Jetzt da ich weiß, dass ich den kompletten Satz aus der *.csv-Datei in ein Feld bekomme, werde ich mir vermutlich sowieso eine neue Funktion mit free und SQL basteln, die mir einen String mit jeweils einem Datensatz der *.csv-Datei an das Programm zurückgibt.

B.Hauser
29-01-20, 06:02
Hmmm, ich würde eine SQL (Tabellen) Funktion basteln, die mir die komplette Tabele auflöst.

Schau Dir mal die SQL-Funktionen GET_CLOB_FROM_FILE, sowie die Tabellen Funktion SYSTOOLS.SPLIT() an.

Mit GET_CLOB_FROM_FILE kannst Du direkt auf die IFS-Datei zugreifen.
Mit SPLIT() kannst Du einen String in einzelne Zeilen aufsplitten.

Dann brauchst Du nur eine Common Table Expression (CTE), die die IFS-Datei zunächst einzelne Sätze (beim CRLF) aufsplittet. In einer zweiten CTE splittest Du dann die Zeilen in Spalten auf.
Im Endgültigen SELECT musst Du das Ganze nur noch in Spalten ausgeben ... und voilà du liest eine CSV-Datei direkt aus dem IFS und gibst das Ganze in Spalten aus.

Etwa so:



With x as (Select Ordinal_Position as RowKey, Element as RowInfo
from Table(SysTools.Split(Get_Clob_From_File('/home/Hauser/Employee.csv'), x'0D25')) a
Where Trim(Element) > ''),
y as (Select x.*, Ordinal_Position ColKey,
Trim(B '"' from Element) as ColInfo
from x cross join Table(SysTools.Split(RowInfo, ',')) a)
Select RowKey,
Min(Case When ColKey = 1 Then ColInfo End) EmployeeNo,
Min(Case When ColKey = 2 Then ColInfo End) Name,
Min(Case When ColKey = 3 Then ColInfo End) FirstName,
Min(Case When ColKey = 4 Then ColInfo End) Address,
Min(Case When ColKey = 5 Then ColInfo End) Country,
Min(Case When ColKey = 6 Then ColInfo End) ZipCode,
Min(Case When ColKey = 7 Then ColInfo End) City
From y
Where RowKey > 1
Group By RowKey;



Im übrigen wenn Du mit SQL arbeitest, darf eine VarChar-Variable 32767 Byte nicht überschreiten. längere alphanumerische Variablen, die Du mit SQL verarbeiten möchtest, musst Du mit dem Schlüssel-Wort SQLTYPE als CLOB definieren (maximum 16 MB).

Du kannst natürlich auch mir (embedded) SQL direkt auf IFS-Dateien zugreifen. In diesem Fall musst Du dann mit File-Referenz-Variablen arbeiten, die bebenfalls mit SQLTYPE definiert werden. In diesem Fall kannst du sogar IFS-Dateien bis zu 2 GB verarbeiten.

Birgitta

Fuerchau
29-01-20, 08:53
Alles gut und schön, aber warum immer alles selber machen, wenn es bereits CPYFRMIMPF gibt?
Hier wird insbesonders auch auf die Zeichenfeldproblematik mit Anführungszeichen, STRDLM + STRESCCHR, berücksichtigt, Kopfzeile ausgeblendet und Typkonvertierung incl. Null-Flag durchgeführt.
Fehler werden in einer Protokolldatei ausgegeben, also alles das, was man mit obigem statischen SQL nicht machen kann.
Ich muss mir nur 1x die Mühe machen die Zieltabelle korrekt zu erstellen;-).

B.Hauser
30-01-20, 05:08
und warum sollte ich mir die Mühe machen einmalig eine Zieltabelle zu erstellen und die Daten dann da reinkopieren, um sie im Anschluss dann auszulesen und die Daten zu verarbeiten?

Anstatt einmalig ein SQL-Statement zu erstellen, dass die Daten direkt aus dem IFS über ein SELECT statement ausliest und verarbeiten kann und zwar OHNE Zwischendatei. Da es sich um SQL handelt, können die Daten mit Hilfe von WHERE-Bedingungen gezielt gefiltert und auch z.B. mit einem INSERT Statement direkt dahin übertragen werden, wo sie hingehören.

Im übrigen werden in meinem Beispiel die führenden und folgenden Anführungszeichen entfernt und auch die Überschrift ignoriert.

Birgitta

Fuerchau
30-01-20, 07:53
Dann lies doch bitte meinen Beitrag genauer. Mit SQL löst du nicht die Probleme STRDLM + STRESCCHR.
Außerdem kann es schon mal vorkommen, dass das Trennzeichen in einer Zeichenkette vorkommt und dann scheitert der Split.
Und meine Erfahrung sagt mir, dass es sich dabei eher selten um Einmalaktionen handelt sondert i.d.R. es sich um Importschnittstellen handelt. Und das würde ich dann schon (in meiner persönlichen Ansicht) stabiler lösen wollen.
Der weitere Vorteil ist die Typsicherheit da es keiner weiteren Konvertierung bezgl. Zahlen und Datum gibt. Die Daten in der Tabelle sind direkt mit weiteren SQL-Methoden weiterverarbeitbar.
Für Einmalaktionen verwende ich da gerne den einfachen 5250-Upload.

Und ob ich mir die Mühe mache, den SQL solange auszuprobieren bis er passt oder ob ich mal eben einen CREATE TABLE und CPYFRMIMPF aufrufe sei mal dahningestellt was da schneller ist.

Es gibt einfach viele Lösung bei der IBM i incl. diverser Excel-Tools und ich nehme für mich meistens den einfachen Weg.
Das sind ja auch nur Vorschläge.