[NEWSboard IBMi Forum]
  1. #1
    cbe is offline [professional_User]
    Registriert seit
    May 2005
    Beiträge
    392

    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

  2. #2
    Registriert seit
    Feb 2001
    Beiträge
    20.707
    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.
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

  3. #3
    cbe is offline [professional_User]
    Registriert seit
    May 2005
    Beiträge
    392
    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

  4. #4
    Registriert seit
    Feb 2001
    Beiträge
    20.707
    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().
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

Similar Threads

  1. Konvertierung nach Graphic --> CCSID Problem
    By codierknecht in forum NEWSboard SAP
    Antworten: 32
    Letzter Beitrag: 09-02-18, 13:00
  2. QIMGCVTI: Konvertierung von PDF nach AFP
    By Daechsle in forum NEWSboard Programmierung
    Antworten: 0
    Letzter Beitrag: 05-03-12, 11:54
  3. RTF-DCA Konvertierung
    By agutenbru in forum IBM i Hauptforum
    Antworten: 10
    Letzter Beitrag: 22-08-06, 16:00
  4. Konvertierung DEC nach CHAR
    By cbe in forum NEWSboard Programmierung
    Antworten: 7
    Letzter Beitrag: 24-05-06, 08:58
  5. EBCDIC Codetabellen
    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
  •