-
Konvertierung 2-Byte Unicode und EBCDIC nach UTF-8
Hallo allerseits,
diese Anforderung haben sicher noch mehr Leute außer mir, evtl. kann es ja der ein oder andere gebrauchen:
UTF-8 ist ein Format, in dem nicht jedes Zeichen eine feste Länge hat.
die unteren 127 Zeichen des ASCII sind identisch in UTF-8, höhere ASCII-Zeichen und andere werden mit 2, 3, oder mehr Byte dargestellt.
Wen der Aufbau näher interessiert: https://de.wikipedia.org/wiki/UTF-8
Es ist gar nicht so schwer, dieses Format zu generieren. Der Code ist so kurz, dass ich dies viel einfacher finde, als irgendwelche APIs zu bedienen, die dann bei den Feinheiten doch nicht das tun, was ich will.
Und wenn etwas fehlt, kann man es leicht anpassen/ergänzen.
Wen es interessiert, hier ein kurzer Abriss, wie das Programm arbeitet:
Eingangsparameter: fTxtC enthält den 2-Byte-Unicode String, dataLen ist die Länge (muss mind. 1 sein)
(1) Jedes Zeichen besteht aus 2 Byte, dies wird einzeln konvertiert,
(2) und hierfür in eine Zahl (binN) umgewandelt.
Abhängig von der Größe der Zahl ergibt sich als Länge der Zielzeichenkette:
(3a) 1 (ASC),
(3b) 2,
(3c) 3
oder 4 – hier nicht implementiert.
Am Ende hat man in fTxt8 den fertigen UTF-8 String.
Code:
D DS
D binN 9B 0
D binA1 1 1A
D binA2 2 2A
D binA3 3 3A
D binA4 4 4A
*
D fTxtE S 1A dim(2000)
D fTxt8 S 1A dim(4000)
D fTxtC S 2A dim(4000)
*
D DS 8002
D textCn
D textCnA 3 8002A
* 2-Byte Unicode ---> UTF-8
C movea *blank fTxt8
C z-add *zero i8 5 0
*
C 1 do dataLen iC 5 0 (1)
C move fTxtC(iC) aE 2
*
C z-add 0 binN CN-Zeichen binär (2)
C movel aE binA3 verarbeiten
C move aE binA4
C select
*
C when binN < x'80' bis 7f -> direkt (3a)
C add 1 i8
C move binA4 fTxt8(i8)
*
C when binN < x'0800' bis '7ff' -> 2 Byte (3b)
C eval binN = %bitand(binN : x'003f')
C + %bitand(binN *4: x'001f00')
C + x'c080'
C add 1 i8
C move binA3 fTxt8(i8)
C add 1 i8
C move binA4 fTxt8(i8)
*
C when binN < x'010000' bis 'ffff' -> 3 Byte (3c)
C eval binN = %bitand(binN : x'00003f')
C + %bitand(binN *4: x'003f00')
C + %bitand(binN *16: x'0f0000')
C + x'e08080'
C add 1 i8
C move binA2 fTxt8(i8)
C add 1 i8
C move binA3 fTxt8(i8)
C add 1 i8
C move binA4 fTxt8(i8)
*
C other
C add 1 i8
C move x'3f' fTxt8(i8) sonst ?
C endsl
*
C enddo
Und der Vollständigkeit halber gleich noch eine einfache Konvertierung EBCDIC UTF-8
Auch hier ein kurzer Abriss, wie das Programm arbeitet:
Eingangsparameter: data enthält den EBCDIC-String, dataLen ist die Länge
(1) Jedes Zeichen wird einzeln konvertiert,
(2) Die Position des Zeichens in c$ASC20 addiert mit 31 ergibt den ASC-Wert
(3) 8-Bit-Zeichen (über 127) oder Nicht-druckbare Zeichen frage ich explizit ab, das sind ja nicht viele.
Am Ende hat man in fTxt8 wieder den fertigen UTF-8 String.
Code:
D DS
D binN 9B 0
D binA1 1 1A
D binA2 2 2A
D binA3 3 3A
D binA4 4 4A
*
D fTxtE S 1A dim(2000)
D fTxt8 S 1A dim(4000)
D fTxtC S 2A dim(4000)
*
Dc$ASC20 S 95A inz(' !"#$%&''()*+,-./-
D 0123456789:;<=>?-
D @ABCDEFGHIJKLMNO-
D PQRSTUVWXYZ[\]^_-
D `abcdefghijklmno-
D pqrstuvwxyz{|}~')
*
* EBCDIC ---> UTF-8
C movea *blank fTxtE
C movea *blank fTxt8
C movea data fTxtE
C z-add *zero i8 5 0
C 1 do dataLen iE 5 0 (1)
C move fTxtE(iE) aE 1
C add 1 i8
*
C aE scan c$ASC20 n 5 0 50 (2)
C select
C *in50 wheneq *on
C n add 31 binN
C move binA4 fTxt8(i8)
C aE wheneq 'ä' ä (3)
C movea x'c3a4' fTxt8(i8)
C add 1 i8
C aE wheneq 'ö' ö
C movea x'c3b6' fTxt8(i8)
C add 1 i8
C aE wheneq 'ü' ü
C movea x'c3bc' fTxt8(i8)
C add 1 i8
C aE wheneq 'ß' ß
C movea x'c39f' fTxt8(i8)
C add 1 i8
C aE wheneq 'Ä' Ä
C movea x'c384' fTxt8(i8)
C add 1 i8
C aE wheneq 'Ö' Ö
C movea x'c396' fTxt8(i8)
C add 1 i8
C aE wheneq 'Ü' Ü
C movea x'c39c' fTxt8(i8)
C add 1 i8
C aE wheneq x'0d' CR
C movea x'0d' fTxt8(i8)
C aE wheneq x'25' LF
C movea x'0a' fTxt8(i8)
C other
C move x'3f' fTxt8(i8) sonst ?
C endsl
*
C enddo
-
Du bist dir darüber im Klaren, dass das nur funktioniert, wenn dein Job zur Laufzeit die selbe CCSID hat wir zur Erstellzeit deines Programmes?
Mit einer anderen CCSID des Jobs und/oder der Datenbank geht das mit den Sonderzeichen in die Hose.
Und wo sind die Accent-Zeichen wie "éèê" usw.?
Es geht viel einfacher:
Convert a Graphic Character String (CDRCVRT, QTQCVRT) API
Zu übergeben ist die Zeichenkette sowie die Von und Zu-CCSID.
Die Von-CCSID ist die Job-CCSID (wenn sie nicht gerade mal wieder 65535 ist) und die ZielCCSID ist dann 1208 (UTF-8) oder sonstwas (1252, 13488), also auch von UNICODE in UTF-8 und Retour.
-
Convert a Graphic Character String (CDRCVRT, QTQCVRT) API
die Beschreibung sieht wirklich vielversprechend und leicht verwendbar aus - werde ich mal ausprobieren.
Auf jeden Fall war es eine nette Fingerübung, und hilft beim Verstehen wie UTF-8 aufgebaut ist
-
Und das Ganze baue ich mir in eine RPGLE-Wrapperfunktion ein, die ich dann überall beliebig aufrufen kann.
Im übrigen ist dieses API nicht langsamer als iConv().
Similar Threads
-
By codierknecht in forum NEWSboard SAP
Antworten: 32
Letzter Beitrag: 09-02-18, 13:00
-
By Daechsle in forum NEWSboard Programmierung
Antworten: 0
Letzter Beitrag: 05-03-12, 11:54
-
By agutenbru in forum IBM i Hauptforum
Antworten: 10
Letzter Beitrag: 22-08-06, 16:00
-
By cbe in forum NEWSboard Programmierung
Antworten: 7
Letzter Beitrag: 24-05-06, 08:58
-
By Arbi in forum IBM i Hauptforum
Antworten: 8
Letzter Beitrag: 13-10-01, 20:08
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