PDA

View Full Version : Unicode / UTF-8 Streamfile lesen



Seiten : 1 2 [3] 4

Fuerchau
24-04-19, 08:58
Natürlich besteht da die Gefahr, allerdings prüft ja der Compiler bereits nichts, so dass Überschreiber schon immer möglich sind.
Das Schlüsselwort CONST verhindert nur zur Compilezeit ein Überschreiben durch Fehlermeldungen, allerdings nicht den Zugriff auf falsch definierte Speicherbereiche.
Da ein Serviceprogramm ohne Änderung des Aufrufers erneuert werden kann, merkt die Laufzeit hier nichts, da es keine Signaturprüfung gibt.

Rainer Ross
24-04-19, 11:26
Hallo Dieter,

kleiner Tipp mit rtnparm geht es noch etwas schneller


dcl-pi *n varucs2(300000) rtnparm;


Herzliche Grüße
Rainer Ross

Webanwendungen auf IBM i so schnell wie Greescreen - Hier klicken und testen
http://www.myhofi.com/tms/HTML/MySubfileApp.html
(http://www.myhofi.com/tms/HTML/MySubfileApp.html)
Selektion Umsatz, Kredit und Saldo geht über < oder > oder <= oder >=
siehe https://docs.webix.com/datatable__filtering.html#number

dschroeder
24-04-19, 12:24
Vielen Dank. Dass mit rtnparm kannte ich noch nicht. Trotz des Nachlesens in der RPG Reference bin ich mir noch nicht ganz sicher, was es tut. In der Referenz steht, dass es Vorteile hat, wenn die realen Rückgabewerte klein sind. Dann wird wohl weniger Speicher benötigt. Die Frage ist, ob es immer funktioniert.

andreaspr@aon.at
25-04-19, 10:22
Hi Dieter,

eigentlich ist der Vorteil dann, wenn die Rückgabewerte groß sind.
Normal wird eine Kopie beim Returnwert erstellt. Beim RTNPARM wird lediglich die Speicheradresse (Pointer) vom Wert zurückgegeben.
Das ist dann am schnellsten.

lg Andreas

Fuerchau
25-04-19, 14:39
Dann les dazu mal die Beschreibung:

The RTNPARM keyword specifies that the return value of a procedure is to be handled internally as a
parameter of the same type as the defined returned value, passed by reference.

Da der zusätzliche Parameter unbenannt ist, lässt er sich also nicht direkt ansprechen.
Die Wirkung entfaltet sich erst, wenn man ein Ergebns im Return spezifiziert, da dieses dann nicht in einer Zwischenvariablen sondern direkt übergeben wird.

Es bringt aber keinen Vorteil, wenn man sowieso eine benannte Variable benötigt die dann beim Return den Wert doch wieder kopieren muss.
Ansonsten: laut Doku bringt es besonders bei großen Returnwerten etwas, da der automatische Speicher dadurch nicht belastet wird.

Zu beachten sind aber besonders die Hinweise bzgl. %PARMS und %PARMNUM, da diese Funktionen den Wert um 1 größer melden.

BenderD
25-04-19, 14:57
... das ist wieder so eine typische RPG-Denke. Das sind auf heutigen Rechnern nicht mal Mikrosekunden, die man da vermeintlich einspart und den eigentlichen Pferdefuß übersieht man: die RTNPARM Arie verhindert caching, was in vielen Fällen mehr bringt. Was Speicher sparen angeht: das verträgt sich nicht mit der zunehmenden Verfettung der RPG Runtime durch Gimmicks wie dynamische Feldgruppen (hier sei am Rande erwähnt, dass es schon seit langem Open Source Komponenten gibt, die das besser können).

D*B

dschroeder
08-08-19, 11:42
Du kannst auch mit SQL gezielt auf Daten zugreifen und dir nur das rausholen, was Du brauchst.
File-Referenz-Variablen kannst Du mit SQL-Funktionen genau wie alphanumerische Felder behandeln, d.h. mit POSSTR oder LOCATE kannst Du positionieren und suchen, mit SUBSTR kannst Du Daten gezielt herauslesen und dann in eine (kürzere) Host-Variable ausgeben.
... und Du bist auch nicht auf 16MB beschränkt, sondern kannst die ganzen (möglichen) 2GB verarbeiten. (Die Daten werden überigens nicht kopiert)

Beispiel:


DCL-S MyClobFile SQLTYPE(CLOBFILE) CCSID(1208);
...
MyCLOBFile_Name = %Trim(ParIFSFile);
MyCLOBFile_NL = %Len(%Trim(MyCLOBFile_Name));
MyCLOBFile_FO = SQFRD; //Read Only

For Index = 1 to 15;
Start = (Index-1) * RowLen + 1;
Exec SQL Set :MyText = Substr(:MyCLOBFile, :Start, :RowLen);
Dsply MyText;
If SQLCODE = 100 or SQLCODE < *Zeros
or %Len(%Trim(MyText)) = *Zeros;
Leave;
EndIf;
EndFor;


Birgitta


Hinweis für alle, die sich für dieses Thema interessieren: Das Programmbeispiel von Birgitta ist fast korrekt. Der SQLTYPE muss allerdings mit Unterstrich getrennt werden: CLOB_FILE.

Aber mit einer anderen Sache haben wir ganz schön gekämpft: Im obigen Beispiel greift man mit substr auf den Clob zu. Das funktioniert nicht korrekt, wenn es sich um Mixed Data Strings handelt ! Das ist bei UTF-8 der Fall, wo ja die einzelnen Zeichen durch unterschiedliche viele Bytes ausgedrückt werden. Substr akzeptiert zwar einen UTF-8 String, interpretiert die Positionsangaben aber als Byte, nicht als Zeichen!

(Steht in der SQL Referenz "im Kleingedruckten").

Die Lösung ist aber einfach: Es gibt zusätzlich die Funktion "substring" (also alles ausgeschrieben). Die Funktion kann mit echten Zeichenzählungen umgeben!

Aber nochmals Danke an Birgitta für das Programmbeispiel. Hat uns sehr weitergeholfen!

Dieter

dschroeder
14-08-19, 10:30
Noch ein Hinweis:
Auch die SQL Funktion length kommt mit Mixed Byte Strings (wie UTF-8) nicht zurecht. Es gibt aber die Funktion character_length. Die zählt echte Zeichen und nicht etwa Bytes!

Fuerchau
14-08-19, 16:48
Was hilft einem das für Substring?
Bei der Angabe der CCSID zur CLOB_FILE könnte man mal versuchen die 1200 für UCS16 zu verwenden.
Dann sollte beim Lesen der Datei von 1208 in 1200 gewandelt werden und Substring wieder funktionieren.
Performant ist das nicht gerade. Einfacher wäre dann, die Datei in einen Lob-Locator vom Typ DBCLOB abzulegen. Dann kann man per Substring ja darauf zugreifen.
Dann wird nur 1x auf die IFS-Datei zugegriffen, der Rest passiert im Speicher.
Vergiss nicht, den Locator auch wieder frei zu geben.

dschroeder
15-08-19, 09:35
substring funktioniert ja mit utf-8. Nur substr geht nicht! Ich wollte nur darauf hinweisen, dass es inzwischen einige SQL Funktionen gibt, die auf den ersten Blick genau das machen, was die alten Funktionen (substr, length) auch gemacht haben. Aber die neuen Funktionen (substring, character_length) funktionieren eben auch bei UTF-8 korrekt, während die alten Funktionen falsche Ergebnisse liefern.

Zu dem Freigeben muss ich aber nochmal nachfragen: Ich mache den Zugriff ja wie im obigen Beispiel beschrieben:
DCL-S MyClobFile SQLTYPE(CLOBFILE) CCSID(1208);
...
MyCLOBFile_Name = %Trim(ParIFSFile);
MyCLOBFile_NL = %Len(%Trim(MyCLOBFile_Name));
MyCLOBFile_FO = SQFRD;

Dann arbeite ich auf dem Clob mit den SQL-Funktionen substring und character_length. Muss ich danach nochmal irgendetwas freigeben?