Windows 11 Terminal/PowerShell auf UTF-16 Unicode umstellen



  • @tech-house sagte in Windows 11 Terminal/PowerShell auf UTF-16 Unicode umstellen:

    Dein Vorschlag funktioniert leider nicht, ich habe http://www.unifoundry.com/pub/unifont/ installiert, und jetzt sind da noch mehr Fragezeichen, anstatt weniger.

    Und ... echo "╭╮╯╰" funktioniert bei mir auch, das ändert aber nichts an der Ausgabe des Kommandozeilenprogramms.

    Wenn echo funktioniert zeigt es dass powershell und die eingestellte font das können.
    Bist du sicher das dein Programm utf-16 ausgibt?
    Entweder dein Programm gibt kein utf-16 aus oder die verwendete ausgabefunktion konvertiert die daten z.b. in die lokale codepage bevor diese die powershell erreichen.

    Wie sieht der code des Programms für die ausgabe aus?



  • @tech-house sagte in Windows 11 Terminal/PowerShell auf UTF-16 Unicode umstellen:

    Die Commands chcp und chcp 65001 funktionieren zwar, aber, wie bereits gezeigt, werden nicht alle Zeichen dargestellt.

    Die Codepage 65001 ist eigentlich auch UTF-8, wie @firefly schon schrieb wäre es mal gut, deinen Ausgabe-Code zu sehen. Für direkte UTF-16-Ausgabe würde ich auch vermuten, dass man das über std::wcout machen müsste. Mit std::cout liegen dann nämlich noch einige Konvertierungen dazwischen, entweder von der C-Runtime und/oder dem Terminal, was dieses Thema generell immer etwas fummelig macht, wenn man es richtig hinbekommen will.

    In persönlich mache mit C++ immer UTF-8-Ausgabe um das zwischen Linux und Windows zu vereinheitlichen und für Windows nicht zu viel extra Code schreiben zu müssen. Das sieht dann etwa so aus:

    #include <iostream>
    #ifdef _WIN32
         #include <Windows.h>
    #endif
    
    auto main() -> int
    {
        #ifdef _WIN32
            SetConsoleOutputCP(CP_UTF8); // Das ist de facto `chcp 65001`
        #endif
        std::cout << "╭╮╯╰" << std::endl;
    }
    

    Das funktioniert zumindest bei mir so problemlos (Windows Terminal mit Powershell und "Inconsolata" als Schriftart).

    Wichtig ist dabei, dass der Quellcode auch in UTF-8 ohne BOM gespeichert wurde. Das ist soweit ich weiss bei Visual Studio nicht Standard. Dort muss die Datei als "Unicode (UTF-8 without signature) - Codepage 65001" gespeichert werden.

    Wenn es unbedingt UTF-16 sein soll, kann ich so auf Anhieb nicht weiterhelfen. Eigentlich sollte UTF-16 auch die Standard-Ausgabeformat für Powershell wie auch allen unter Windows, das mit "Unicode" zu tun hat sein. Da sollte man eigentlich nichts "umstellen" müssen, probiers einfach mal mit std::wstring , std::wcout und L"abc"-String-Literalen.



  • @Finnegan sagte in Windows 11 Terminal/PowerShell auf UTF-16 Unicode umstellen:

    Wichtig ist dabei, dass der Quellcode auch in UTF-8 gespeichert wurde. Das ist soweit ich weiss bei Visual Studio nicht Standard. Dort muss die Datei als "Unicode (UTF-8 without signature) - Codepage 65001" gespeichert werden.

    Alternativ kann man die zeichen auch in "escaped" form (\u<hexzahl>) verwenden.
    z.b. "╭" ist U+256D => "\u256D"

    Um auf dein Beispiel zu münzen

    std::cout << "╭╮╯╰" << std::endl;
    

    würde es dann so aussehen

    std::cout<<"\u256D\u256E\u256F\u2570";
    

    Dadurch ist man unabhängig der verwendeten kodierung des source codes.



  • @firefly sagte in Windows 11 Terminal/PowerShell auf UTF-16 Unicode umstellen:

    @Finnegan sagte in Windows 11 Terminal/PowerShell auf UTF-16 Unicode umstellen:

    Wichtig ist dabei, dass der Quellcode auch in UTF-8 gespeichert wurde. Das ist soweit ich weiss bei Visual Studio nicht Standard. Dort muss die Datei als "Unicode (UTF-8 without signature) - Codepage 65001" gespeichert werden.

    Alternativ kann man die zeichen auch in "escaped" form (\u<hexzahl>) verwenden.
    z.b. "╭" ist U+256D => "\u256D"

    Mit den Escape-Codes hab ich noch nicht herumgespielt, ich hatte aber mal vor einiger Zeit ein paar Kombinationen getestet mit sehr unterschiedlichen Ergebnissen:

    https://www.c-plusplus.net/forum/topic/343499/utf-8-strings-und-sonderzeichen-visual-studio-2015/5

    Letztendlich finde ich die Lösung, die Datei als UTF-8 zu speichern und die Konsole auf CP_UTF8 zu setzen die beste, weil der Code dadurch am einfachsten wird. Keine String-Präfixe, keine Escapes. Einfach nur hinschreiben, was man ausgeben will - so wie es IMHO sein sollte: Unicode als "Normalfall", nicht als "Sonderfall". Dafür nehm ich dann gern in Kauf auf die Datei-Codierung achten zu müssen 😉 .



  • @Finnegan Jo die Verwendung von utf-8 für text files sollte man generell vorziehen.
    Nur macht das halt Visual Studio von haus aus leider nicht dass es überhaupt eine unicode codierung nutzt für text files sonder standardmäßig die lokale codepage des systems dafür nutzt



  • @tech-house sagte in Windows 11 Terminal/PowerShell auf UTF-16 Unicode umstellen:

    Wie kann ich denn einen Unicode-Zeichensatz nachinstallieren, der nahezu alle UTF-16-Zeichen unterstützt? Am besten monospace.

    Die nerdfonts dürften deine Wünsche abdecken.



  • @firefly sagte in Windows 11 Terminal/PowerShell auf UTF-16 Unicode umstellen:

    @Finnegan Jo die Verwendung von utf-8 für text files sollte man generell vorziehen.
    Nur macht das halt Visual Studio von haus aus leider nicht dass es überhaupt eine unicode codierung nutzt für text files sonder standardmäßig die lokale codepage des systems dafür nutzt

    Ich behaupte mal solche Dinge sind mit einer der Hauptgründe, weshalb wir uns auch 2023 noch mit so einem archaischen Scheiss (sorry!) herumschlagen müssen 😝



  • @Finnegan Seit VS2017 kann man das was mit der .editorconfig machen.
    https://stackoverflow.com/questions/41335199/how-to-config-visual-studio-to-use-utf-8-as-the-default-encoding-for-all-project/65945041#65945041

    Wobei ich was gelesen habe, dass es mittlerweile bei default utf-8 sein soll. Da ich aktuell kein Visual Studio zu hand habe kann ich das nicht nachprüfen.

    Aber da die non Unicode api von windows UTF-8 bei default nicht verwendet sondern ANSI codepage hilft es nicht wenn der code in UTF-8 gespeichert wird.

    Da hilft es nur entweder die wide char variante der api zu nutzen oder via SetConsoleOutputCP(CP_UTF8);
    Die consolen ausgabe auf UTF-8 umzustellen statt default ANSI



  • @firefly sagte in Windows 11 Terminal/PowerShell auf UTF-16 Unicode umstellen:

    Aber da die non Unicode api von windows UTF-8 bei default nicht verwendet sondern ANSI codepage hilft es nicht wenn der code in UTF-8 gespeichert wird.

    Das ist in der Tat ein Problem. Für ein reines Windows-Programm, dass hauptsächlich Funktionen der Windows-API verwendet, würde ich daher auch eher UTF-16 empfehlen. Bei den Programmen, an denen ich meist arbeite, ist das aber so gut wie nie der Fall, daher wird dort eben an der Schnittstelle zum OS entsprechend zu UTF-16 konvertiert. Das ist die "Windows wird auch unterstützt"-Perspektive, die sicher nicht jeder hat 😁


  • Gesperrt

    @firefly sagte in Windows 11 Terminal/PowerShell auf UTF-16 Unicode umstellen:

    Wie sieht der code des Programms für die ausgabe aus?

    Hier ist der Code der Java-Library:

    https://github.com/MitchTalmadge/ASCII-Data/blob/master/src/main/java/com/mitchtalmadge/asciidata/graph/ASCIIGraph.java#L141

    In der Java-Anwendung rufe ich: System.out.println(ASCIIGraph.fromSeries(...).plot()); auf, wobei ... ein double[] ist. Aus der Java-Anwendung generiere ich eine runnable jar.

    Ich bin erst heute Abend wieder da... bis später



  • Tja da haben wir das problem. System.out verwendet/öffnet stdout (standard out) mit einer "default" encoding, welche wohl unter windows dann die verwendung von einer codepage entspricht.
    Und nicht einer unicode kodierung.

    Laut https://stackoverflow.com/questions/20386335/printing-out-unicode-from-java-code-issue-in-windows-console
    Soll dass hier funktionieren

    public static PrintWriter stdout = new PrintWriter(
        new OutputStreamWriter(System.out, StandardCharsets.UTF_8),
        true);
    

    und dann

    stdout.println
    

    verwenden statt

    System.out.println
    

    Wobei laut dem stackoverflow thread das scheinbar nicht immer funktioniert.
    Daher solltest du das vorher testen ob unicode auch ausgegeben wird
    z.b. mit
    stdout.println("\u256D");
    Sollte dann "╭" ausgeben.

    Falls das nicht funktioniert hilft eventuell der hier beschriebene workaround damit powershell utf-8 verwendet für input/output statt OEM codepage:

    https://github.com/PowerShell/PowerShell/issues/7233


  • Gesperrt

    @firefly Danke, aber es geht leider (noch) nicht... Mit

    private static final PrintWriter stdout = new PrintWriter(new OutputStreamWriter(System.out, StandardCharsets.UTF_8), true);
    

    kommt leider Gemüse raus:

      614,00 Ôöñ                                                               Ôò¡ÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔò«
      613,00 Ôöñ                                                      Ôò¡ÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔò»               Ôò░ÔöÇÔò«
      612,00 Ôöñ                                             Ôò¡ÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔò»                          Ôò░ÔöÇÔöÇÔöÇÔò«
      611,00 Ôöñ                                            Ôò¡Ôò»                                       Ôò░ÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔò«
      610,00 Ôöñ                                            Ôöé                                               Ôò░ÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇ
      609,00 Ôöñ                                      Ôò¡ÔöÇÔöÇÔöÇÔöÇÔöÇÔò»
      608,00 Ôöñ                                   Ôò¡ÔöÇÔöÇÔò»
      607,00 Ôöñ                               Ôò¡ÔöÇÔöÇÔöÇÔò»
      606,00 Ôöñ                     Ôò¡ÔöÇÔò«Ôò¡ÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔò»
      605,00 Ôöñ           Ôò¡ÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔò» Ôò░Ôò»
      604,00 Ôöñ Ôò¡ÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔöÇÔò»
      603,00 ÔöñÔò¡Ôò»
      602,00 Ôö╝Ôò»
    

    Mit einem der anderen Charsets:

    Charset
    Description
    US-ASCII
    Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the Unicode character set
    ISO-8859-1  
    ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1
    UTF-8
    Eight-bit UCS Transformation Format
    UTF-16BE
    Sixteen-bit UCS Transformation Format, big-endian byte order
    UTF-16LE
    Sixteen-bit UCS Transformation Format, little-endian byte order
    UTF-16
    Sixteen-bit UCS Transformation Format, byte order identified by an optional byte-order mark
    

    kommt leider auch nur Gemüse raus...

    Aber immerhin: Die Ausgabe ist nun eine andere, nur anscheinen nicht UTF16 ...


  • Gesperrt

    Ich dachte, es läge vielleicht an der JVM, aber das hat leider auch nicht funktioniert:
    https://stackoverflow.com/questions/44208347/unable-to-set-correct-encoding-in-powershell

    Ein Versuch mit dieser neuen Methode hat auch nicht geklappt:
    https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/PrintStream.html#write(byte[])

    Es ist seltsam, dass es in der IntelliJ Konsole funktioniert (IJ hatte ich auf UTF8 umgestellt), in der PowerShell hingegen nicht, und man scheinbar daran auch nichts ändern kann, außer vielleicht die betreffenden Zeichen auszutauschen.^^



  • Tja wenn man nicht lesen kann...

    Für die Person, welche das hier irgendwann lesen sollte.
    Eine reine Einstellung in java ist so nicht möglich.
    Man muss die Powershell selbst umstellen, dass es utf-8 nutzt für die ausgabe.
    Denn wenn die powershell via startmenu eintrag gestartet wird, so wird die selbe codepage genutzt, welche auch von der cmd.exe genutzt wird.

    Dafür kann der workaround in dem github link verwendet werden.

    [console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding
    

    Dadurch wird auch die unicode zeichen, welche via System.out.println ausgegeben werden korrekt dargestellt.

    Wobei ich das jetzt nur mit powershell 5.1 (welches bei Windows 10 dabei ist) getestet habe.


Anmelden zum Antworten