-
Unicode / UTF-8 Streamfile lesen
Hallo,
ich habe mir einige Serviceprogramme geschrieben, mit denen ich Streamfiles bequem lesen kann. Ich nutze dazu die UNIX Type APIs. Z.B. "read".
Code:
D AnzBytes S 10U 0
D AnzGelesen S 10P 0
D buffer S 64000A
AnzGelesen = read(handle:%addr(buffer):AnzBytes)
Das ganze funktioniert allerdings nur, wenn in der Streamfile ein Single Byte Character Set drinsteht. Wenn ich eine Streamfile erzeuge, die UTF-8 oder Unicode beinhaltet, stürzt das Programm ab.
In der Doku zu "read" steht auch, dass damit nur eine genaue Anzahl von Bytes gelesen wird. Ich will aber eigentlich keine Bytes lesen, sondern Zeichen.
Hat jemand dieses Problem bereits gelöst? Gibt es eine empfehlenswerte API-Funktion, mit der man Zeichen (auch Unicode oder UTF-8) lesen kann?
Vielleicht fällt ja jemandem etwas über die Feiertage ein! Im Voraus vielen Dank!
Frohe Ostern.
Dieter
-
-
Vielen Dank für deine Antwort.
Grundsätzlich ginge das mit SQL. Was mich stört, ist allerdings, dass ich dann die ganze Datei immer "am Stück" handeln muss. Mit den reads und seeks könnte ich mich auch in sehr großen Dateien bewegen und die interessanten Stellen lesen.
Wenn ich keine besseren APIs finde, werde ich es aber wohl erstmal mit SQL umsetzen. Wenn ich den ganzen SQL-Code in einem Serviceprogramm kapseln möchte, dem ich einen Pfad und Dateinamen mitgebe und das mir dann den Dateiinhalt komplett als String zurückgibt, müsste ich im Serviceprogramm ja schon ziemlich große Datenstrukturen für SQLTYPE deklarieren. Da könnte schnell die 16 MB Speichergrenze erreicht werden. Gerade bei Unicode.
-
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:
Code:
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
-
Siehst du, geht doch alles.
Und wieso 16MB-Grenze?
Wenn du auf *TERASPACE gehst, in der gesamten Prozesskette, kannst du Speicher bis 2Tera ansprechen. Da platzt dir wahrscheinlich eher die Platte.
Im Service erbst du das Speichermodell und der Rufer gibt sein Speichermodell vor. Alles sehr flexibel.
Je ACTGRP kann ein anderes Speichermodell gewählt werden.
Vorteil von SQL:
Alle möglichen String-Funktionen können verwendet werden.
Alle CCSID's können verwendet werden.
Automatische CCSID-Wandlung inclusive.
Wenn du mein Beispiel siehst, nehme ich als Ziel DBCLOB, das ist UCS2-Code. Im Singlestorage max. 8 MB. Aber so große Dateien habe ich im Schnittstellenbereich nicht gehabt, und dann gibts ja noch Birgittas Hinweise.
Ich nehme af diesem Weg z.B. EDI-Dateien auseinander. Für EDI-XML's definiere ich passende Strukturen und verwende dann den XML-INTO.
Übrigens generell in UCS2/UTF16, da schon mal gerne der Job auf 65535 belassen wird.
Nachtrag:
Da ein Service ja von verschiedenen Programmteilen aufgerufen werden kann, muss man sich natürlich Zerstückelungslogiken sehr genau überlegen. Nicht dass während der Verarbeitung einer dazwischen grätscht.
Interessant sind Ansätze wie CALLBACK-Verarbeitung (Procedurpointer). In diesem Fall ist ein Service auch Rekursiv benutzbar.
Oder man generiert sich einen "FileControlBlock" (kennt man irgendwoher), der relevante Stati festhält. Da könnte man auch Repositionierungen durchführen und viele Dateien gleichzeitig bearbeiten. SQL hält die Datei nämlich nicht geöffnet.
-
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)
Welcome back Birgitta,
ich hoffe, Du bereicherst weiterhin dieses Forum und lässt Dich nicht wieder vertreiben
Herzliche Grüße
Rainer Ross
-
Zitat von Fuerchau
Siehst du, geht doch alles.
Und wieso 16MB-Grenze?
Wenn du auf *TERASPACE gehst, in der gesamten Prozesskette, kannst du Speicher bis 2Tera ansprechen. Da platzt dir wahrscheinlich eher die Platte.
Im Service erbst du das Speichermodell und der Rufer gibt sein Speichermodell vor. Alles sehr flexibel.
Je ACTGRP kann ein anderes Speichermodell gewählt werden.
Dann versuch doch mal eine Variable oder Datenstruktur > 16MB zu definieren oder mit SQL einen Pointer zu verarbeiten.
Birgitta
-
Zitat von Fuerchau
Siehst du, geht doch alles.
Und wieso 16MB-Grenze?
Wenn du auf *TERASPACE gehst, in der gesamten Prozesskette, kannst du Speicher bis 2Tera ansprechen.
Ich meine, *TERASPACE bringt nur etwas bei eigener Speicherallozierung mit %alloc.
Die Speichernutzung für "normale" RPG-Variablen ist meiner Meinung nach auf 16MB begrenzt. Wobei ich mir im Moment nicht sicher bin, ob die 16 MB pro Job, pro Call-Ebene oder pro ACTGRP gelten.
-
Vielen Dank für die beiden Antworten. Ich werde eurem Rat folgen und das ganze mit SQL machen!
Viele Grüße,
Dieter
-
Was die Pointer angeht, so muss ich sogar via SQLDA Pointer angeben (nebst SQLType und Attributen).
Somit kann ich auch schön per %ALLOC Speicher zur Verfügung stellen.
SQLDA's werden dann per "using" bei den entsprechenden SQL-Befehlen angegeben.
Dann kann ich eben auch innherhalb von RPGLE wiederum mit Pointern umgehen.
Zu beachten ist noch folgendes:
In meinem Beispiel habe ich 8MB Unicode (CCSID 1200) verwendet. Sollte die Datei tatsächlich mal größer sein, sollte man hier dann mit LOB-Locator umgehen: GET_[DB/C]LOB_FROM_FILE.
Der Vorteil des Locator's besteht halt darin, dass das Lesen der Datei und die Codewandlung in den Speicher nur 1x passiert.
Anschließend kann man sich per SQL-Stringfunktionen dann die Teile herausholen.
Dies dürfte wohl performanter sein, als sich die Daten scheibchenweise aus der Datei zu holen, zumal bei UTF-8 eine Zeichenposition direkt ja nicht errechenbar ist (UTF-8 => 1-4Byte je Zeichen).
-
Irgendwie klappt das bei mir noch nicht:
Code:
dcl-s clobFile sqltype(CLOB_FILE) CCSID(1200);
dcl-s text varucs2(300000);
clobFile_Name = %trim(file);
clobFile_NL = %len(%trim(clobFile_Name));
clobFile_FO = SQFRD; //Read Only
exec sql set :text = :clobFile;
return text;
Beim Kompilieren bekomme ich immer:
"Variable TEXT nicht definiert oder nicht verwendbar. Reason: No declaration for the variable exists, the declaration is not within the current scope, or the variable does not have an equivalent SQL data type."
Hat jemand eine Idee?
-
Das Problem hat sich erledigt. Habe einen Doppelpunkt vor der Variable "TEXT". Der darf da nicht hin.
Similar Threads
-
By dschroeder in forum NEWSboard Programmierung
Antworten: 5
Letzter Beitrag: 29-03-19, 13:56
-
By Theo in forum IBM i Hauptforum
Antworten: 3
Letzter Beitrag: 02-03-18, 12:46
-
By dschroeder in forum NEWSboard Programmierung
Antworten: 7
Letzter Beitrag: 12-12-17, 13:32
-
By Rainer Ross in forum NEWSboard Programmierung
Antworten: 5
Letzter Beitrag: 28-10-16, 16:16
-
By Bleil in forum IBM i Hauptforum
Antworten: 2
Letzter Beitrag: 13-10-01, 20:15
Berechtigungen
- Neue Themen erstellen: Nein
- Themen beantworten: Nein
- You may not post attachments
- You may not edit your posts
-
Foren-Regeln
|
Erweiterte Foren Suche
Google Foren Suche
Forum & Artikel Update eMail
AS/400 / IBM i
Server Expert Gruppen
Unternehmens IT
|
Kategorien online Artikel
- Big Data, Analytics, BI, MIS
- Cloud, Social Media, Devices
- DMS, Archivierung, Druck
- ERP + Add-ons, Business Software
- Hochverfügbarkeit
- Human Resources, Personal
- IBM Announcements
- IT-Karikaturen
- Leitartikel
- Load`n`go
- Messen, Veranstaltungen
- NEWSolutions Dossiers
- Programmierung
- Security
- Software Development + Change Mgmt.
- Solutions & Provider
- Speicher – Storage
- Strategische Berichte
- Systemmanagement
- Tools, Hot-Tips
Auf dem Laufenden bleiben
|
Bookmarks