OemToCharBuffW macht nicht das gleiche wie OemToCharBuffA und anschließender Umwandlung nach Unicode

Ein Stück Code in unserer Software behandelt Datenimport aus fremden Dateien. Nicht wenige alter DOS Programme erzeugen ja Daten im „OEM“-Zeichensatz (DBase etc.).
Wir haben in der Vergangenheit immer streng die T-Notation verwendet und eigentlich sollte dies einen vor vielen Überraschungen bewahren. Aber Pustekuchen.

Folgender Code sollte Daten aus einem OEM-Stream in einen CString umwandeln und eigentlich bin ich davon ausgegangen, dass das Ergebnis für Tabulatoren (‚\t‘) und Zeilenschaltungen („\r\n“) ergebnisneutral ist. D.h. in anderen Worten ich erwartete in dem String genauso viele Tabulatoren und Zeilenschaltungen vor wie nach der Konvertierung.
Die Umwandlung erfolgte mit solch einem Stück Code:

CString strText;
::OemToCharBuff(szText,CStrBuf(srText,len),len);

Sieht eigentlich harmlos aus. Allerdings musste ich feststellen, dass hier OemToCharBuffA und OemToCharBuffW ganz und gar nicht korrespondierende Ergebnisse liefern.
In der Unicode Version, also in der Version die OemToCharBuffW verwendet, wurden Tabulatoren zu 0x25cb L’○‘ wchar_t  und Zeilenschaltungen zu 0x266a L’♪‘ wchar_t und 0x25d9 L’◙‘ wchar_t!

Führt man jedoch zuerst eine Kovertierung in den „ANSI/Windows/8bit“-Zeichensatz durch und konvertiert anschließenend diesen ANSI-String nach Unicode, dann ist alles gut und so wie man es erwartet.

Wer Lust hat das nachzubauen kann das mit dem folgenden Code. Wichtig sind eigentlich nicht die OEM-Umlaute sondern nur die Tab- und Zeilenschaltungen:

const char szText[] = "Dies ist ein OEM TestString\r\n"
       "mit Zeilenschaltungen\tund Tabs\r\n"
       "und Umlauten:\r\n"
       "Ž=AE, ™=OE, š=šE\r\n"
       "„=ae, ”=oe, =ue, á=ss";
const size_t len = sizeof(szText);

CStringW strOut1;
::OemToCharBuffW(szText,CStrBufW(strOut1,len),len);
CStringA strOut2;
::OemToCharBuffA(szText,CStrBufA(strOut2,len),len);
CStringW strOut3(strOut2);

_ASSERT(strOut1.Compare(strOut3)==0); // Das sollte eigentlich gleich sein

PS: Getestet habe ich das auf einem Windows 7 64bit und 32bit OS.

Siehe folgende Links zu den Begriffen OEM/ANSI:
http://blogs.msdn.com/b/oldnewthing/archive/2005/10/27/485595.aspx
http://blogs.msdn.com/b/oldnewthing/archive/2005/03/08/389527.aspx

Ein Gedanke zu „OemToCharBuffW macht nicht das gleiche wie OemToCharBuffA und anschließender Umwandlung nach Unicode“

  1. Ich denke, dass OemToCharBuffW() intern
    MultiByteToWideChar(CP_OEMCP, MB_USEGLYPHCHARS…) benutzt.

    Also besser gleich selbst MultiByteToWideChar() ohne MB_USEGLYPHCHARS benutzen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

I accept that my given data and my IP address is sent to a server in the USA only for the purpose of spam prevention through the Akismet program.More information on Akismet and GDPR.

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.