2012-06-28 10 views
8

Ich arbeite gerade an einem Hobby-Projekt (C/C++), das sowohl mit Windows als auch mit Linux arbeiten soll, mit voller Unterstützung für Unicode. Leider verwenden Windows und Linux verschiedene Kodierungen, die unser Leben erschweren.Cross-Plattform-Unicode in C/C++: Welche Codierung zu verwenden?

In meinem Code versuche ich, die Daten so universell wie möglich zu verwenden, so dass es für Windows und Linux einfach ist. In Windows ist wchar_t standardmäßig als UTF-16 und als UCS-4 in Linux (korrigiere mich, wenn ich falsch liege).

Meine Software öffnet ({_wfopen, UTF-16, Windows}, {fopen, UTF-8, Linux}) und schreibt Daten in Dateien in UTF-8. Bis jetzt ist alles machbar. Bis ich mich dazu entschloss, SQLite zu verwenden.

Die C/C++ - Schnittstelle von SQLite ermöglicht codierte Strings mit einem oder zwei Byte (click). Natürlich funktioniert das nicht mit wchar_t in Linux, da die wchar_t in Linux standardmäßig 4 Bytes ist. Daher erfordert das Schreiben und Lesen von sqlite eine Konvertierung für Linux.

Derzeit ist der Code mit Ausnahmen für Windows/Linux überfüllt. Ich hatte gehofft, um die Standard-Idee der Speicherung von Daten in wchar_t zu halten:

  • wchar_t in Windows: Dateipfade ohne ein Problem, Lesen/Schreiben zu SQLite ohne ein Problem. Das Schreiben von Daten in eine Datei sollte trotzdem in UTF-8 erfolgen.
  • wchar_t in Linux: Ausnahme für die Dateipfade wegen UTF-8-Codierung, Konvertierung vor dem Lesen/Schreiben in sqlite (wchar_t), und das gleiche für Windows beim Schreiben von Daten in eine Datei.
  • Nach dem Lesen (here) war ich überzeugt, ich sollte bei wchar_t in Windows bleiben. Aber nachdem all das funktioniert hatte, begannen die Probleme mit der Portierung auf Linux.

    Zur Zeit denke ich daran, alles mit einfachen Zeichen (UTF-8) zu wiederholen, weil es mit Windows und Linux funktioniert, unter Berücksichtigung der Tatsache, dass ich 'WideCharToMultiByte' jede Zeichenfolge in Windows erreichen muss UTF-8. Die Verwendung von einfachen char * -basierten Strings reduziert die Anzahl der Ausnahmen für Linux/Windows erheblich.

    Haben Sie Erfahrung mit Unicode für Cross-Plattform? Irgendwelche Gedanken über die Idee, Daten einfach in UTF-8 zu speichern anstatt wchar_t zu verwenden?

    +0

    2byte Zeichencodierung ist definitiv * nicht * UTF-16.UTF-16 ist 2 bis 4 Byte und UTF-8 ist 1 bis 4 Byte. Windows 'wchar_t' ist nicht UTF-16, es ist UCS2. In der Praxis bemerken Sie vielleicht den Unterschied nicht, da UCS2 den BMP abdeckt, aber wenn Ihre Benutzer entscheiden, dass sie Daten in Ogham oder Runen haben müssen ... – user268396

    +1

    Windows verwendet UTF-16 und verwendet 'wchar_t', um UTF-16 zu halten Daten, und dies seit Windows 2000 getan. –

    +3

    Wie nützlich wchar_t ist und für was: http://StackOverflow.com/a/11107667/365496 – bames53

    Antwort

    6

    UTF-8 auf allen Plattformen mit Just-in-Time-Konvertierung in UTF-16 für Windows ist eine gängige Taktik für plattformübergreifendes Unicode.

    +0

    Ich würde diese Aussage leicht anpassen und sagen: Native Kodierung auf allen Plattformen mit Just-in-Time-Konvertierung zu/von UTF-8. Diese Just-in-Time-Konvertierung ist immer dann erforderlich, wenn Zeichenfolgen die Anwendung verlassen (z. B. Schreiben in eine Datei, Senden von Daten über einen Netzwerk-Socket, Übergeben von Eingaben an eine Bibliothek usw.). Natürlich kommt es auf das spezifische Szenario an. – IInspectable

    2

    Unsere Software ist auch plattformübergreifend und wir hatten ähnliche Probleme. Wir haben uns entschieden, dass wir möglichst wenig Conversions erzielen möchten. Dies bedeutet, dass wir wchar_t unter Windows und char unter Unix/Mac verwenden.

    Wir tun dies, indem _T und LPCTSTR und ähnliche auf Unix unterstützt und durch generische Funktionen, die zwischen std::string und std::wstring leicht umwandeln. Wir haben auch eine generische std::basic_string<TCHAR> (tstring), die wir in den meisten Fällen verwenden.

    Bisher funktioniert das ganz gut. Grundsätzlich die meisten Funktionen nehmen eine tstring oder eine LPCTSTR und diejenigen, die nicht erhalten ihre Parameter von einer tstring konvertiert werden. Das bedeutet, dass wir unsere Strings meistens nicht konvertieren und die meisten Parameter nicht durchlaufen.

    +2

    Dies ist eine mögliche Lösung, aber immer noch ein bisschen hacky. Aus meiner Lektüre habe ich auch gelernt, dass ich TCHAR vermeiden sollte, da es eingeführt wurde, um die Rückwärtskompatibilität mit älterer Software zu unterstützen, indem ich zu MBCS anstelle des Unicode-Flags wechsle. – ErikKou

    +0

    @Fozi, Wie unterstütze ich _T auf Ubuntu Linux? Vielen Dank. – Frank

    +0

    @ErikKou, Was ist Ihre mögliche Lösung für die Emulation des Windows-Makros _T in Unix oder Linux? Vielen Dank. – Frank