das leidige thema von locales und umlauten



  • hola leute

    irgendwie bin ich was locales, unicode und umlaute betrifft recht begriffsstutzig.
    ich war eigendlich der meinung das zu mindest das ausgeben von strings mit wcout recht problemlos ablaufen sollte.
    pustekuchen.

    ich lade mir strings aus einer unicode datei (enhaelt umlaute) und gebe sie mir dann ganz normal mit wcout auf der console aus.

    die umlaute werden aber nur dann auch dargestellt wenn ich das als locale native, also deutsch, verwende.

    warum ?
    ich dachte die umlaute sollten in unicode eindeutig sein.

    Meep Meep



  • Nein, weil auch die Konsole das richtige Locale haben muß, wenn die Konsole kein Unicode kann.

    Die richtige Kodierung muß doch vom String bis zur Konsole und dessen Font abgestimmt sein. Wenn einer von den Teilnehmern aus der Reihe tanzt, kannste das vergessen.

    Außerdem, was heißt denn bei dir Unicode? Ich gehe davon aus, das du UCS2 bzw. UTF-16 meinst? So weit mir bekannt, kann die Windows-Konsole kein Unicode. Sie kann nur Codepages. Und deshalb mußt du auch deutsch einstellen. Wenn es eine Unicode-Konsole wäre, bräuchte man keine Codepage einstellen. Unicode soll doch gerade den ganzen Codepage-Kram obsolet machen.

    Angeblich soll es ja reichen, den Konsolen-Font (unter Eigenschaften) auf Lucida Console umzustellen, damit die Konsole auf Unicode umgeschaltet wird.



  • hola artchi

    ja ich meinte UTF-16.

    in wikipedia http://en.wikipedia.org/wiki/Win32_console
    steht

    The Client/Server Runtime Subsystem is responsible for Win32 console windows on Windows NT based operating systems.[1]

    Under Windows NT and CE based versions of Windows, the screen buffer uses four bytes per character cell: two bytes for character code, two bytes for attributes. The character is then encoded a 16-bit subset of Unicode (UCS-2).[2] For backward compatibility, the console APIs exist in two versions: Unicode and non-Unicode. The non-Unicode versions of APIs can use code page switching to extend the range of displayed characters (but only if TrueType fonts are used for the console window, thereby extending the range of codes available). Even UTF-8 is available as "code page 65001".

    das klingt fuer mich so, das ich die locales bzw. codepages nur brauche wenn ich nicht mit wcout arbeite.

    schriftart hab ich Lucida Console eingestellt.

    ausserdem wuerde es fuer mich dann keinen sinn machen mit UTF-16(unicode) zu arbeiten wenn ich dann wieder das gleiche problem habe wie mit cout(non-unicode).

    Meep Meep



  • Wie hast du denn deine Umlaute im Sourcecode eingegeben?



  • hola

    im sourcecode gar nicht. einmal uebers resource-script von VC und einmal eingelesen von einer textdatei.

    bin inzwischen schon drauf gekommen das es folgend unabhaengig vom locale funktioniert:

    const wchar_t *str;
       ::LoadStringW(::GetModuleHandleW(0), IDS_Teststring, reinterpret_cast<wchar_t*>(&str), 0);
    
       std::wcout << str << std::endl; /* (1) */
    
       HANDLE console = ::GetStdHandle(STD_OUTPUT_HANDLE);
       ::WriteConsoleW(console, str, wcslen(str), 0, 0); /* (2) */
       std::wcout << std::endl;
    

    die zeile (2) schreibt die umlaute richtig raus, egal welches locale geladen ist.
    bei zeile (1) nur wenn ich das locale native verwende.

    Meep Meep



  • hola

    das problem ansich liegt bei den streams.
    das std-codecvt facet aendert jedes wchar_t element in ein char element.
    deshalb wird bei einem 'wofstream' auch nur single-bytes geschrieben anstatt wide-chars.
    das kann man jedoch umgehen, indem mein ein eigenes codecvt-facet verwendet.
    nachteil: man muss den wofstream im binary-mode oeffnen wodurch ein

    stream << std::endl;
    

    nur als '000A' in den stream geschrieben wird.
    was aber nicht so tragisch ist, da man einfach ein wendl selber definiert das dann '000D000A' in den stream schreibt und flushed.

    das mit dem codecvt facet funktioniert aber nicht mit wcout.

    WriteConsoleW funktioniert auch nur, da es direkt in den consolenbuffer schreibt.
    bringt den grossen nachteil, das es bei verwendung von pipes in der console den ausgegebenen text nicht verwenden kann.

    beispiel:

    wchar_t *test = L'test';
    WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), test, 8, 0 ,0);
    

    wenn ich nun in der console

    meinprogramm.exe > datei.txt
    

    eingebe, bleibt die datei 'datei.txt' leer.

    ansich brauch ich aber die pipes usw nicht. deshalb ueberlege ich mir ob ich nicht einfach einen eigenen streambuf schreibe, der dann WriteConsoleW zur ausgabe verwendet. bleibt natuerlich abzuwarten ob das mit einem eigenen streambuf ueberhaupt erledigt ist oder andere teile wie codecvt trotzdem mir noch das leben schwer machen.

    wenn sonst noch jemand eine idee oder ansatzpunkt hat, immer her damit
    🙂

    Meep Meep


Anmelden zum Antworten