WriteConsoleW
scheint eine ziemlich magische Funktion zu sein.
procedure WriteLnToConsoleUsingWriteFile(CP: Cardinal; AEncoding: TEncoding; const S: string);
var
Buffer: TBytes;
NumWritten: Cardinal;
begin
Buffer := AEncoding.GetBytes(S);
// This is a side effect and should be avoided ...
SetConsoleOutputCP(CP);
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), Buffer[0], Length(Buffer), NumWritten, nil);
WriteLn;
end;
procedure WriteLnToConsoleUsingWriteConsole(const S: string);
var
NumWritten: Cardinal;
begin
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), PChar(S), Length(S), NumWritten, nil);
WriteLn;
end;
const
Text = 'АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ';
begin
ReadLn; // Make sure Consolas font is selected
// Works, but changing the console CP is neccessary
WriteLnToConsoleUsingWriteFile(CP_UTF8, TEncoding.UTF8, Text);
// Doesn't work
WriteLnToConsoleUsingWriteFile(1200, TEncoding.Unicode, Text);
// This does and doesn't need the CP anymore
WriteLnToConsoleUsingWriteConsole(Text);
ReadLn;
end.
Also zusammenfassend:
WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), ...)
unterstützt UTF-16.
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), ...)
unterstützt UTF-16 nicht.
Meine Vermutung wäre, dass die klassischen Pascal I/O verwendet, um verschiedene ANSI-Kodierungen zu unterstützen, die WriteFile
Aufruf.
Denken Sie auch daran, dass, wenn auf einer Datei statt der Konsole verwendet es als gut zu funktionieren hat:
unicode text file output differs between XE2 and Delphi 2009?
Das bedeutet, dass WriteConsole
Pausen Ausgabeumleitung blind verwenden. Wenn Sie WriteConsole
verwenden, sollten Sie zurück zu WriteFile
wie diese fallen:
var
NumWritten: Cardinal;
Bytes: TBytes;
begin
if not WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), PChar(S), Length(S),
NumWritten, nil) then
begin
Bytes := TEncoding.UTF8.GetBytes(S);
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), Bytes[0], Length(Bytes),
NumWritten, nil);
end;
WriteLn;
end;
Beachten Sie, dass die Umleitung der Ausgabe mit einer beliebigen Codierung in cmd.exe
gut funktioniert. Es schreibt den Ausgabestrom einfach unverändert in die Datei.
PowerShell erwartet jedoch entweder ANSI-Ausgang oder die korrekte Präambel (/ BOM) muss am Anfang der Ausgabe enthalten sein (oder die Datei wird malencoded!). Auch PowerShell konvertiert die Ausgabe immer in UTF-16 mit Präambel.
MSDN recommendsGetConsoleMode
mit, um herauszufinden, ob der Standard-Griff eine Konsole Griff ist, auch die Stückliste genannt:
Writeconsole schlägt fehl, wenn es mit einem Standard-Griff verwendet wird, die in eine Datei umgeleitet wird. Wenn eine Anwendung die mehrsprachige Ausgabe verarbeitet, die umgeleitet werden kann, ermitteln Sie, ob das Ausgabehandle ein Konsolenhandle ist (eine Methode besteht darin, die GetConsoleMode-Funktion aufzurufen und zu überprüfen, ob es erfolgreich ist). Wenn das Handle ein Konsolenhandle ist, rufen Sie WriteConsole. Wenn das Handle kein Konsolenhandle ist, wird die Ausgabe umgeleitet und Sie sollten WriteFile aufrufen, um die E/A durchzuführen. Stellen Sie sicher, dass eine Unicode-Textdatei mit einer Byte-Reihenfolge markiert. Weitere Informationen zu Informationen finden Sie unter Verwenden von Byte Order Marks.
['Mögliches Duplikat '] (http://stackoverflow.com/q/265018/960757)? Ich denke, [Antwort von Tndrej] (http://stackoverflow.com/a/268202/960757) deckt Ihre Frage ab. – TLama
@TLama Ich habe diese Frage gesehen. Ich denke, das ist anders. Ich möchte wissen, ob es einen Weg gibt, Writeln Unicode zu respektieren. Vielleicht durch eine RTL-Funktion das Verhalten der Schalter aufrufen. –
Nur Hinweise: http://www.bobswart.nl/Weblog/Blog.aspx?RootId=5:3011. Außerdem: http: //edn.embarcadero.com/article/39022 –