Unicode-Textdateiausgabe unterscheidet zwischen XE2 und Delphi 2009?

8

Wenn ich den folgenden Code versuche, scheint es in XE2 anders zu sein als in D2009.

%Vor%

Kompilieren mit XE2 auf einem Windows 8 PC gibt in WordPad

??  C

txt Hex-Code: EF BB BF 3F 3F 0D 0A B0 43 0D 0A

Kompilieren mit D2009 auf einem Windows XP PC gibt in Wordpad

总结 ° C

txt hex-Code: EF BB BF E6 80 BB E7 BB 93 0D 0A B0 43 0D 0A

Meine Fragen sind, warum es anders ist und wie kann ich chinesische Zeichen in einer Textdatei unter Verwendung der alten Textdatei I / O speichern?

Danke!

    
Thomas 09.01.2013, 10:16
quelle

3 Antworten

14

Ab XE2 verfügt AssignFile() über einen optionalen CodePage -Parameter, mit dem der Wert festgelegt wird Codepage der Ausgabedatei:

%Vor%

Write() und Writeln() haben beide Überladungen, die UnicodeString und WideChar Eingaben unterstützen.

Sie können also eine Datei erstellen, deren Codepage auf CP_UTF8 gesetzt ist, und dann konvertiert Write/ln() Unicode-Zeichenfolgen automatisch in UTF-8, wenn Sie sie in die Datei schreiben.

Der Nachteil ist, dass Sie die UTF-8-Stückliste nicht mehr mit AnsiChar -Werten schreiben können, da die einzelnen Bytes in UTF-8 konvertiert werden und somit nicht korrekt geschrieben werden. Sie können das umgehen, indem Sie die Stückliste als einzelnes Unicode-Zeichen schreiben (was es wirklich ist - U+FEFF ) anstatt als einzelne Bytes.

Dies funktioniert in XE2:

%Vor%

Wenn Sie möchten, dass zwischen D2009 und XE2 etwas kompatibler und zuverlässiger ist, verwenden Sie stattdessen TStreamWriter :

%Vor%

Oder führen Sie die Datei-E / A manuell aus:

%Vor%     
Remy Lebeau 09.01.2013, 18:21
quelle
6

Sie sollten den alten Text-I / O nicht mehr verwenden.

Wie auch immer, Sie können TEncoding verwenden, um die UTF-8-TBytes wie folgt zu erhalten:

%Vor%

Ich bin mir nicht sicher, ob es eine einfachere Möglichkeit gibt, TBytes in eine Textdatei zu schreiben, vielleicht hat jemand anderes eine bessere Idee.

Bearbeiten:

Bei einer reinen Binärdatei ( File anstelle von TextFile type) kann BlockWrite verwendet werden.

    
Jens Mühlenhoff 09.01.2013 10:50
quelle
5

Es gibt ein paar verräterische Zeichen, die Ihnen sagen können, was beim Umgang mit Unicode falsch war. In Ihrem Fall sehen Sie " ? " in der resultierenden Ausgabedatei: Sie erhalten Fragezeichen, wenn Sie versuchen, etwas von Unicode in eine Code-Seite zu konvertieren, und die Ziel-Codepage kann nicht die angeforderten Zeichen darstellen.

Beim Betrachten des Hexadezimalspeichers ist es offensichtlich (Zeilenabschlusszeichen zählen), dass die Fragezeichen das Ergebnis des Speicherns der zwei chinesischen Zeichen in der Datei sind. Die zwei Zeichen wurden in genau zwei Fragezeichen umgewandelt. Dies sagt Ihnen, dass Writeln() entschieden hat, Ihnen zu helfen, und konvertiert den Text von UTF8 (eine Unicode-Darstellung) in Ihre lokale Codepage. Das Delphi-Team hat sich wahrscheinlich dafür entschieden, da die alten I / O-Routinen nicht UNICODE-kompatibel sein sollten; Da Sie mit den alten I / O-Routinen eine UTF8-Zeichenfolge schreiben, helfen sie Ihnen dabei, diese in Ihre Code-Seite umzuwandeln. Du magst diese helfende Hand nicht begrüßen, aber es bedeutet nicht, dass es falsch war: es ist ein Gebiet ohne Papiere.

Da Sie jetzt wissen, warum das passiert, wissen Sie, was zu tun ist, um es zu stoppen. Lassen Sie WriteLn() wissen, dass Sie etwas senden, das nicht konvertiert werden muss. Sie werden feststellen, dass das nicht besonders einfach ist, da Delphi XE2 Ihnen anscheinend "aushilft". Zum Beispiel ändert sich bei solchen Dingen nicht nur der String-Typ, sondern wird in AnsiString konvertiert, indem die Code-Seiten-Konvertierungsroutine durchlaufen wird, die Ihnen Fragezeichen liefert:

%Vor%

Aus diesem Grund und wenn Sie One-Liner-Lösungen benötigen, können Sie eine Konvertierungsroutine versuchen, etwa so:

%Vor%

Sie können dann Folgendes tun:

%Vor%

Und es wird tun, was Sie erwarten (ich habe es tatsächlich vor dem Posten versucht!)

Natürlich ist die einzige WAHRE Antwort auf diese Frage, dass Sie den ganzen Weg zu Delphi XE2 hochgerüstet haben:

Beenden Sie die Verwendung veralteter E / A-Routinen und wechseln Sie zu TStream-basiert

    
Cosmin Prund 09.01.2013 12:58
quelle

Tags und Links