Unicode- und Codepage-Unterstützung in der Natural-Programmiersprache

#### Search Results

Search

# Unicode- und Codepage-Unterstützung in der Natural-Programmiersprache

Dieses Kapitel behandelt folgende Themen:

- Natural-Datenformat U für Unicode-basierende Daten

- Natural-Statements

- Logische Bedingungen

- Systemvariablen

- Große und dynamische Variablen

- Session-Parameter

- Beispiel-Programme

## Natural-Datenformat U für Unicode-basierende Daten

In der Natural-Programmiersprache können Sie Unicode-Zeichenketten mit Format U und U-Konstanten angeben.

- Format U
  Im Format U können Sie Daten definieren, die Unicode-Zeichenketten enthalten. Das Natural-Datenformat U ist intern UTF-16.

  Siehe auch Format und Länge von Benutzervariablen im Leitfaden zur Programmierung.

- U-Konstante
  Sie können Unicode-Konstanten mit dem Präfix "U" definieren. Zum Beispiel:

      U'Äpfel'

  Das Präfix "UH" kann benutzt werden, um Unicode-Konstanten in hexadezimalem Format zu definieren. Vier hexadezimale Ziffern stellen gemäß Unicode Standard eine UTF-16-Codeeinheit (Code Unit) dar. Daher muss die Gesamtlänge ein Vielfaches von Vier sein. Angenommen, Sie benötigen die hexadezimale Form von

      U'Äpfel'

  dann brauchen Sie die UTF-16-Codeeinheiten für "Ä", "p", "f", "e" und "l" (die sind "U+00C4", "U+0070", "U+0066", "U+0065" und "U+006C") und Sie müssen sie zu folgender hexadezimalen Zeichenkette zusammenfügen:

      UH'00C4007000660065006C'

  Siehe auch Unicode-Konstanten im Leitfaden zur Programmierung.

Das Datenformat U ist Endian-abhängig. Dies ist beim Übertragen (`MOVE`) zwischen den Formaten B und U zu berücksichtigen.

### Format U im Vergleich zu A

Der Vorteil des Formats U (im Verleich zum Format A) liegt darin, dass es beliebige Zusammenfügungen von Zeichen aus verschiedenen Sprachen enthalten kann und dass es nicht von der Standard-Codepage (Wert der Systemvariablen `*CODEPAGE`) abhängig ist. Darüber hinaus vereinfacht das Format U den Austausch von Daten zwischen unterschiedlichen Plattformen. Es sind keine Umwandlungen (z.B. von EBCDIC nach ASCII) nötig.

Andererseits wird für Daten im Format U mehr Speicherplatz als bei Daten im Format verbraucht. Bei Sprachen, die in Einzel-Byte-Zeichencodierung dargestellt werden können, führt das Format U dazu, dass Zeichenketten doppelt so viel Platz belegen, wie früher erforderlich war. Bei ostasiatischen Sprachen dagegen ist der Speicherplatzverbrauch oft nicht größer.

## Natural-Statements

Grundsätzlich gilt, dass das Format U in den meisten Statements benutzt werden kann, die das Format A erlauben. Wenn aber ein Natural-Objektname als Operand eines Statements gegeben ist (z.B. im `CALLNAT`-Statement), dann kann das Format U nicht benutzt werden, weil Natural-Objekte das Format A haben. Informationen zu bestimmten Statements können Sie der Statements-Dokumentation entnehmen.

Grundsätzlich können die Formate A und U zusammen in einem Statement benutzt werden, z.B.:

    EXAMINE S FOR P WITH DELIMITER D REPLACE R

dabei ist `S` im Format U und `P`, `D` und `R` sind im Format A.

Im obigen Beispiel werden die Variablen `P`, `D` und `R` vor der tatsächlichen Ausführung des `EXAMINE`-Statements temporär in das Zielformat U umgewandelt. Die Umwandlung von Unicode nach Codepage oder umgekehrt erfordert den Aufruf einer ICU-Funktion. Diese Umwandlung beansprucht zusätzliche Rechenzeit und zusätzlichen Speicherplatz. Dieser Nachteil wird bei sehr großen Variablen noch größer. Um häufige Umwandlungen zu vermeiden, wird deshalb empfohlen, innerhalb eines Statements nur ein Format zu benutzen. Wenn alle Operanden im obigen Beispiel entweder im Format U oder im Format A angegeben werden, entfällt die Notwendigkeit einer Umwandlung. Wenn Sie sich jedoch dafür entscheiden, nur Operanden im Format U anzugeben, dann ist diese Variante (artbedingt) langsamer, weil dieser Operandentyp mehr Ressourcen verbraucht. Ein Zeichen wird dann mit 2 Bytes kodiert (anstelle von 1 Byte, das für das Format A benutzt wird).

Bei einer Umwandlung (insbesondere vom Format U ins Format A) besteht immer das Risiko, dass Zeichen nicht in der Ziel-Codepage dargestellt werden können. Angenommen Sie wollen das Unicode-Zeichen "U+05D0" (hebräischer Buchstabe Alef) in die Codepage IBM01140 (Englisch) umwandeln. Da dieses Zeichn in der Codepage IBM01140 nicht enthalten ist, wird entweder das Ersatzzeichen für diese Codepage benutzt oder der Platzhalter, der bei der Definition der Codepage im Modul `NATCONFG` angegeben worden ist. Wenn der Profilparameter `CPCVERR` auf `ON` gesetzt ist, wird in diesem Fall eine Fehlermeldung ausgegeben, die einen Umwandlungsfehler anzeigt. Die ursprüngliche Information geht auf jeden Fall verloren.

Bei der Benutzung von Unicode sind insbesondere die folgenden Statements betroffen:

- MOVE NORMALIZED

- MOVE ENCODED

- EXAMINE

- PARSE JSON

- PARSE XML

- REQUEST DOCUMENT

- DEFINE PRINTER

- CALLNAT (RPC)

### MOVE NORMALIZED

Normalisierung in Unicode: Ein Vorgang zum Entfernen alternativer Darstellungen von äquivalenten Zeichenfolgen aus Textdaten, um die Daten in eine Form umzuwandeln, die binär auf Äquivalenz verglichen werden kann. Im Unicode Standard sind verschiedene Normalisierungsformen definiert. Die Normalisierungsform, die sich bei der kanonischen Zerlegung einer Unicode-Zeichenkette ergibt, und die im Anschluss daran (wo möglich) erfolgende Ersetzung aller zerlegten Zeichenfolgen durch Primärkompositen wird "Normalization Form Composed" (NFC) genannt.

Natural nimmt an, dass alle Unicode-Daten im NFC-Format sind, um sicherzugehen, dass String-Operationen ohne teilweise Trunkierung eines Unicode-Zeichens durchgeführt werden können. Bei den Umwandlungsoperationen in Natural wird sichergestellt, dass die resultierenden Unicode-Zeichenkette in NFC ist. Wenn Unicode-Daten von Außerhalb von Natural empfangen werden und wenn nicht gewährleistet ist, dass die Daten NFC-Format haben, kann das Natural-Statement `MOVE NORMALIZED` angewendet werden.

Beispiel:

Zeichenfolge | NFC
--- | ---
ê (U+00EA) | ê (U+00EA)
e (U+0065) + ^ (U+0302) | ê (U+00EA)

Anmerkung
Wenn zwei oder mehr Zeichenketten im NFC-Format verkettet werden, kann es sein, dass das Resultat nicht im NFC-Format ist.

### MOVE ENCODED

Eine implizite Umwandlung zwischen Unicode und der Standard-Codepage (Wert der Systemvariablen `*CODEPAGE`) wird durchgeführt, wenn Zeichenketten mittels `MOVE`-Statement von Format U nach Format A oder umgekehrt übertragen werden.

Weiterhin kann das `MOVE ENCODED`-Statement zur Umwandlung zwischen verschiedenen Codepages oder von einer beliebigen verfügbaren Codepage nach Unicode und umgekehrt benutzt werden. Dies kann hilfreich sein, wenn Daten von Außerhalb von Natural kommen und wenn diese Daten in einer Codepage, die ungleich zur Standard-Codepage ist, kodiert sind. Aber Sie können dieses Statement sogar zur Umwandlung zwischen der Standard-Codepage und Unicode benutzen, wenn Sie einen potenziellen Umwandlungsfehler mit der `GIVING`-Klausel erhalten wollen; wenn `CPCVERR` auf `ON` gesetzt ist, wird in diesem Fall das `MOVE`-Statement mit einem Laufzeitfehler stoppen.

Falls ein Zeichen nicht umgesetzt werden kann, hängt es von der Einstellung des `CPCVERR`-Parameters ab, ob ein Ersatzzeichen für dieses Zeichen benutzt wird oder ob die Umwandlung fehlschlägt.

Dieses Statement kann außerdem von U-Daten in das UTF-8-Format benutzt werden.

Anmerkung
Wenn Sie Daten in eine Codepage umwandeln, die ungleich der Standard-Codepage ist, wird empfohlen, diese Daten nicht bei Ein- und Ausgaben zu benutzen. Ein- und Ausgaben sind nur in der Standard-Codepage sinnvoll.

### EXAMINE

Ein "Graphem" ist das, was sich ein Benutzer normalerweise unter einem Zeichen vorstellt. In den meisten Fällen ist ein Unicode-Codepoint ein Graphem, aber ein Graphem kann auch aus mehreren Unicode-Codepoints bestehen.Zum Beispiel ist eine Folge von einem Basiszeichen und einem oder mehreren Kombinationszeichen ein Graphem.

Beispiel: "a" (U+0061) + "." (U+0323) + "^" (U+0302) definiert ein Graphem, das wie folgt angezeigt wird:

Anmerkung
Wenn eine Basis-/Kombinationszeichenfolge normalisiert wird, bedeutet dies nicht, dass die Folge immer durch ein zusammengesetzes (precomposed) Zeichen ersetzt wird, da nicht alle Zeichen im zusammengesetzten Format verfügbar sind.

Ein ergänzender Codepoint ist ein Unicode-Codepoint zwischen "U+10000" und "U+10FFFF". Ein ergänzender Codepoint wird in UTF-16 durch ein Surrogatpaar (Ersatzpaar) dargestellt, das aus zwei Codeeinheiten besteht, wobei der erste Wert des Paares eine "high-surrogate code unit" und der zweite eine "low-surrogate code unit" ist. Solche Zeichn sind im Allgemeinen selten, aber einige werden z.B. als Teil chinesischer und japanischer Personennamen verwendet, und daher ist die Unterstützung dieser Zeichen häufig für Regierungsanwendungen in ostasisatischen Ländern erforderlich.

Die Statements zur Behandlung von Zeichenketten, z.B. `EXAMINE` und die Option `SUBSTRING` arbeiten mit UTF-16-Codeeinheiten. Es liegt in der Verantwortung des Benutzer, dass der Code keine Grapheme oder Surrogatpaare trennt.

Die Klauseln `CHARPOSITION` und `CHARLENGTH` des `EXAMINE`-Statement (siehe Syntax 3 - EXAMINE für Unicode-Grapheme) können jedoch benutzt werden, um den Anfang und die Länge (in UTF-16-Codeeinheiten) von Graphemen abzufragen. Die Ergebniswerte können für `SUBSTRING`-Aufrufe verwendet werden. Mit diesen Klauseln ist es möglich, eine Zeichenkette Graphem für Graphem zu durchsuchen.

Beispiel:

    DEFINE DATA LOCAL
    1 #UNICODE-STRING    (U15)
    1 #CODE-UNIT-INDEX   (N4)
    1 #CODE-UNIT-LEN     (N4)
    1 #GRAPHEME-NUMBER   (N4)
    END-DEFINE

    MOVE U'' TO #UNICODE-STRING

    #GRAPHEME-NUMBER := 1

    REPEAT
    EXAMINE
            FULL VALUE OF #UNICODE-STRING
            FOR CHARPOSITION #GRAPHEME-NUMBER
            GIVING POSITION IN #CODE-UNIT-INDEX
            GIVING LENGTH IN #CODE-UNIT-LEN

            DISPLAY #UNICODE-STRING #GRAPHEME-NUMBER #CODE-UNIT-INDEX #CODE-UNIT-LEN

            #GRAPHEME-NUMBER := #GRAPHEME-NUMBER + 1
    WHILE #CODE-UNIT-INDEX NE 0
    END-REPEAT

    END

Ausgabe des obigen Programms:

    Page     1                                                   05-12-15  09:33:49

    #UNICODE-STRING #GRAPHEME-NUMBER #CODE-UNIT-INDEX #CODE-UNIT-LEN
    --------------- ---------------- ---------------- --------------

               1                1                1
               2                2                2
               3                4                1
               4                5                3
               5                8                1
               6                9                3
               7               12                1
               8               13                3
               9                0                0

### PARSE JSON

Das zu parsende Dokument wird immer intern in UTF-8 gewandelt (wenn das Dokument noch nicht in UTF-8 kodiert ist).

Weitere Informationen siehe Beschreibung des Statements `PARSE JSON`.

Siehe auch Statements für Internet und JSON-/XML-Zugriff im Leitfaden zur Programmierung.

### PARSE XML

Das zu parsende Dokument wird immer intern in UTF-16 gewandelt (wenn das Dokument noch nicht in UTF-16 kodiert ist).

Weitere Informationen siehe Beschreibung des Statements `PARSE XML`.

Siehe auch Statements für Internet und JSON-/XML-Zugriff im Leitfaden zur Programmierung.

### REQUEST DOCUMENT

Bei der Übertragung von Daten mit dem `REQUEST DOCUMENT`-Statement erfolgt nomalerweise keine Codepage-Umwandlung. Wenn Sie wollen, dass die ausgehenden und/oder eingehenden Daten in einer spezifischen Codepage zeichencodiert sind, können Sie die Klausel `DATA ALL` und/oder die Klausel `RETURN PAGE` des `REQUEST DOCUMENT`-Statements benutzen, um dies anzugeben.

Weitere Informationen siehe Beschreibung des Statements `REQUEST DOCUMENT`.

Siehe auch Statements für Internet und JSON-/XML-Zugriff im Leitfaden zur Programmierung.

### DEFINE PRINTER

Das `DEFINE PRINTER`-Statement stellt eine `CODEPAGE`-Klausel zur Verfügung, mit der für die Umwandlung von Druckreportdaten in eine Codepage ungleich der Standard-Codepage (Wert der Systemvariablen `*CODEPAGE` gesorgt werden kann.

### CALLNAT (RPC)

Der Austausch von Daten in U-Format via RPC wird unterstützt. Siehe Beschreibung des `CALLNAT`-Statements.

Wenn Daten im Format U von einer Plattform mit Big-Endian-Zeichencodierung an eine Plattform mit Little-Endian-Zeichencodierung oder umgekehrt gesendet werden, wird die Zeichencodierung so angepasst, dass sie konform zur Zeichencodierung der empfangenden Plattform ist. Wenn zum Beispiel Daten in U-Format in Little-Endian-Zeichencodierung auf einer Plattform mit Big-Endian-Zeichencodierung ankommt, werden die Daten in Big-Endian-Zeichencodierung umgewandelt, bevor sie an das Programm übergeben werden. Wenn diese Daten wieder zurückgesendet werden, dann werden sie wieder in Little-Endian-Zeichencodierung zurückgewandelt.

## Logische Bedingungen

In einer logischen Bedingung können Unicode-Operanden zusammen mit alphanumerischen und binären Operanden benutzt werden. Wenn nicht alle Operanden Unicode-Operanden (Format U) sind, werden der zweite alle folgenden Operanden in das Format des ersten Operanden umgewandelt. Wenn ein binäre Operand (Format B) als zweiter oder nachfolgender Operand angegeben ist, muss die Länge des Operanden gerade sein. Es wird angenommen, dass der binäre Operand Unicode-Codepoints enthält.

Wenn der erste Operand ein Unicode-Operand ist (Format U) und der Vergleich daher als Unicode-Vergleich durchgeführt wird, wird der Unicode-Algorithmus benutzt. Der ICU-Algorithmus führt keinen einfachen Binärvergleich durch. Zum Beispiel:

- einige Codepoint, z.B. "U+0000" werden während des Vergleichsvorgangs ignoriert,

- zusammengesetzte Zeichen werden als gleich dem äquivalenten einzelnen Codepunkt angesehen (zum Beispiel der deutsche Buchstabe "ä", der durch "U+00E4" dargestellt wird, und die Kombination der Codepoints "U+0061" und "U+0308" werden von ICU als gleich betrachtet).

Anmerkung
Der Vergleich eines alphanumerischen und einen Unicode-Operanden kann, abhängig von der Reihenfolge der Felder, unterschiedliche Ergebnisse liefern.

Siehe auch Logische Bedingungen im Leitfaden zur Programmierung.

## Systemvariablen

### *CODEPAGE

Die Systemvariable `*CODEPAGE` gibt den IANA-Namen der Standard-Codepage zurück, die intern von Natural für Konvertierungen zwischen Unicode- und Codepage-Formaten benutzt wird.

### *LOCALE

Die Systemvariable `*LOCALE` enthält die Sprache und das Land der aktuellen Locale.

## Große und dynamische Variablen

Das Format kann beo großen und dynamischen Variablen benutzt werden. Bei dynamischen Variablen gibt die Systemvariable `*LENGTH` die Anzahl der UTF-16-Codeeinheiten zurück.

Siehe auch Dynamische Variablen im Leitfaden zur Programmierung.

## Session-Parameter

Folgende Session-Parameter stehen zur Verfügung:

Parameter | Beschreibung
--- | ---
`DL` | Bestimmt die Ausgabelänge eines Felds im Format A oder U. Siehe auch Ausgabelänge — der DL Parameter im Leitfaden zur Programmierung.
`EMU` | Unicode-Editiermaske.
`ICU` | Unicode-Einfügungszeichen.
`LCU` | Vorangestellte Unicode-Zeichen.
`TCU` | Nachgezogene Zeichen in Unicode.

### Session-Parameter DL im Vergleich zu AL

Solange wie Natural noch nicht Unicode-fähig war, war die Länge von alphanumerischen Feldern immer identisch mit der Anzahl der Spalten, die zum Anzeigen des Felds benötigt wurden (Anzahl der Anzeigespalten genannt). Das traf auch bei den ostasiatischen Sprachen zu, die DBCS-Codepages benutzen: Ein Feld im Format A kann nur die Hälfte der Zeichen aufnehmen (A10 zum Beispiel resultiert in A5).

Beispiel:

    DEFINE DATA LOCAL
    1  #A8 (A8)
    END-DEFINE
    #A8 := 'computer'
    WRITE #A8
    #A8 := ''
    WRITE #A8
    END

Der oben gezeigte Code ergibt folgende Ausgabe:

    Page      1 ...

    computer

Bei Feldern im Format U ist die Länge eines Felds nicht mehr identisch mit der Anzahl der Spalten. Zeichen im Format U können eine schmale Länge (z.B. lateinische Zeichen), eine breite Länge (z.B. chinesische Zeichen) oder keine Länge (z.B. zusammengesetzte Zeichen) haben. Deshalb ist völlig unbekannt, wie viele Anzeigespalten ein Feld im Format U benötigt, denn es ist abhängig vom Inhalt des Feldes. Natural kann nicht automatisch entscheiden, wie viele Spalten im Bildschirm reserviert werden müssen: Wird die maximale Länge angenommen, dann werden in der lateinischen Zeichenausgabe große Lücken auftreten. Wird die minimale Länge angenommen, können chinesische Zeichenausgaben nicht vollständig angezeigt werden. Deshalb muss der Natural-Programmierer die Anzeigebreite eines Feldes definieren. Dazu dient der `DL`-Parameter. Der `AL`-Parameter kann für diesen Zweck nicht benutzt werden, weil er bewirkt, dass der Teil des Feldes, der die definierte Feldlänge übersteigt, abgeschnitten wird. Es sollen aber keine Zeichen von dem U-Format-Feld abgeschnitten werden. Es geht vielmehr darum, die Anfangsposition des nachfolgenden Feldes zu definieren.

Beispiel:

    DEFINE DATA LOCAL
    1  #U8 (U8)
    1  #U4 (U4)
    END-DEFINE
    #U8 := 'computer'
    WRITE #U8
    #U4 := U''
    WRITE #U4 (DL=8)
    END

Der oben gezeigte Code ergibt die gleiche Ausgabe wie oben:

    Page      1 ...

    computer

Auf Windows ist es in einer Remote Development-Umgebung mit dem Natural Web I/O Interface Client möglich in einem Feld zu blättern, wenn der für den `DL`-Parameter angegebene Wert kleiner als die reale Anzeigebreite des Feldes ist.

### EMU, ICU, LCU, TCU im Vergleich zu EM, IC, LC, TC

Die Parameter `EMU`, `ICU`, `LCU` und `TCU` ermöglichen es, Zeichen zu verwenden, die nicht in der Standard-Codepage enthalten sind. Sie werden innerhalb des Programms in Unicode-Format gespeichert. Diese Parameter können bei allen Feldformaten benutzt werden.

Die Parameter `EM`, `IC`, `LC` und `TC` können ebenfalls bei U-Format-Feldern benutzt werden. Diese Parameter können außerdem von Nutzen sein, wenn in der Standard-Codepage enthaltene Zeichen in anderen Codepages abweichende Zeichencodierungen haben. Das Euro-Zeichen (€) zum Beispiel hat den Codepoint "0x80" in der Codepage "windows-1252" (Latin 1), jedoch in der Codepage "windows-1251" (Cyrillic) den Codepoint "0x88".

Somit stellt die Benutzung eines Unicode-Parameters (`EMU`, `ICU`, `LCU` or `TCU`) sicher, dass das Euro-Zeichen immer korrekt angezeigt wird, egal welche Codepage auf dem PC installiert ist.

Beispiel für `EMU`:

    DEFINE DATA
    LOCAL
     01 EMPLOYEES-VIEW VIEW OF EMPLOYEES
       02 FIRST-NAME
       02 NAME
       02 SALARY (1)
    END-DEFINE
    *
      READ (6) EMPLOYEES-VIEW
        DISPLAY NAME FIRST-NAME SALARY(1) (EMU=999,999)
      END-READ
    *
    END

Der oben gezeigte Code ergibt folgende Ausgabe:

    Page     1                                                   05-12-15  11:45:36

            NAME              FIRST-NAME       ANNUAL
                                               SALARY
    -------------------- -------------------- --------

    ADAM                 SIMONE               159,980
    MORENO               HUMBERTO             165,810
    BLOND                ALEXANDRE            172,000
    MAIZIERE             ELISABETH            166,900
    CAOUDAL              ALBERT               167,350
    VERDIE               BERNARD              170,100

## Beispiel-Programme

Die Library `SYSEXPG` enthält Beispiel-Programme für die Unicode- und Codepage-Unterstützung in Natural:

Programm | Beschreibung
--- | ---
`UNICOX01` | Listet alle Unicode-Zeichen auf.
`UNICOX02` | Konvertiert Unicode-Zeichen in Codepoints und umgekehrt.
`CODEPX01` | Listet alle Codepages auf und gibt an, ob die Codepage in Natural unterstützt wird und welche Zeichenkodierung sie verwendet. Bei allen unterstützen Codepages werden Services angeboten, die die Zeichen der Codepage auflisten und mit denen eine Zeichenkette von der Codepage in ihre hexadezimale Darstellung und umgekehrt konvertiert werden kann.
`CODEPXL1` | Listet alle Zeichen einer beliebigen Ein-Byte-Codepage auf.
`CODEPXL2` | Listet alle Zeichen einer beliebigen Zwei-Byte-Codepage auf.
`CODEPXC1` | Konvertiert eine Zeichenkette von einer beliebigen Codepage in ihre hexadezimale Darstellung und umgekehrt.

### On this page

- Natural-Datenformat U für Unicode-basierende Daten
- Natural-Statements
- Logische Bedingungen
- Systemvariablen
- Große und dynamische Variablen
- Session-Parameter
- Beispiel-Programme