WriteConsoleW
似乎是一個非常神奇的功能。
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.
因此,在總結:
WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), ...)
支持UTF-16。
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), ...)
不支持UTF-16。
我的猜測是,爲了支持不同的ANSI編碼,經典的Pascal I/O使用WriteFile
調用。
而且要記住,在文件,而不是控制檯使用時必須工作,以及:
unicode text file output differs between XE2 and Delphi 2009?
這意味着,盲目使用WriteConsole
中斷輸出重定向。如果您使用WriteConsole
你應該回落到WriteFile
這樣的:
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;
注意與任何編碼,它輸出重定向在cmd.exe
工作正常。它只是將輸出流寫入文件不變。
但是,PowerShell希望在輸出開始時包含ANSI輸出或正確的前導碼(/ BOM)到(或文件將被編碼!)。另外,PowerShell將始終使用前導碼將輸出轉換爲UTF-16。
使用GetConsoleMode
,以找出是否標準手柄是一個控制檯手柄MSDN recommends,也BOM中提到:如果它是一個標準的句柄是 重定向到一個文件中使用
WriteConsole失敗。如果應用程序處理可重定向的多語言輸出 ,請確定輸出句柄是否爲 控制檯句柄(一種方法是調用GetConsoleMode函數, 檢查它是否成功)。如果手柄是控制檯手柄,請致電 WriteConsole。如果句柄不是控制檯句柄,則重定向輸出爲 ,您應該調用WriteFile來執行I/O。請確保以 爲Unicode純文本文件加上字節順序標記。有關更多 信息,請參閱使用字節順序標記。
['可能重複](http://stackoverflow.com/q/265018/960757)?我認爲['TOndrej的答案'](http://stackoverflow.com/a/268202/960757)涵蓋了你的問題。 – TLama 2014-10-08 10:56:24
@TLama我看到了這個問題。我認爲這是不同的。我想知道是否有辦法使Writeln尊重Unicode。也許通過RTL函數調用開關行爲。 – 2014-10-08 10:59:13
只是提示:http://www.bobswart.nl/Weblog/Blog.aspx?RootId=5:3011。另外:http://edn.embarcadero。com/article/39022 – 2014-10-08 11:28:18