Writeln 是否能够支持 Unicode? [英] Is Writeln capable of supporting Unicode?

查看:32
本文介绍了Writeln 是否能够支持 Unicode?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑这个程序:

{$APPTYPE 控制台}开始Writeln('АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ');结尾.

我的控制台上使用 Consolas 字体的输出是:

<前>????????Z????????????????????????????????????????

Windows 控制台非常有能力支持 Unicode,正如该程序所证明的:

{$APPTYPE 控制台}用途Winapi.Windows;常量Text = 'АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ';无功数字写入:DWORD;开始WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), PChar(Text), Length(Text), NumWritten, nil);结尾.

输出为:

<前>АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѴѴ

可以说服 Writeln 尊重 Unicode,还是它天生就残废?

解决方案

只需通过带有代码页 cp_UTF8SetConsoleOutputCP() 例程设置控制台输出代码页即可.

program Project1;{$APPTYPE 控制台}用途System.SysUtils,Windows;常量Text = 'АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ';无功功率数字写入:DWORD;开始读Ln;//确保选择了 Consolas 字体尝试WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), PChar(Text), Length(Text), NumWritten, nil);SetConsoleOutputCP(CP_UTF8);写Ln;WriteLn('АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ');除了在 E: 例外做Writeln(E.ClassName, ': ', E.Message);结尾;读Ln;结尾.

输出:

АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѴАБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѴѴ

WriteLn() 在内部将 Unicode UTF16 字符串转换为选定的输出代码页 (cp_UTF8).

<小时>

更新:

以上适用于 Delphi-XE2 及更高版本.在 Delphi-XE 中,您需要显式转换为 UTF-8 才能使其正常工作.

WriteLn(UTF8String('АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢїЪЫЬѢѤЮѠѪѮѰѰѲѲѦѪѴѬѲ);

<小时>

附录:

如果在调用 SetConsoleOutputCP(cp_UTF8) 之前在另一个代码页中完成了到控制台的输出,操作系统不会以 utf-8 格式正确输出文本.这可以通过关闭/重新打开 stdout 处理程序来解决.

另一种选择是为 utf-8 声明一个新的文本输出处理程序.

vartoutUTF8:文本文件;...SetConsoleOutputCP(CP_UTF8);分配文件(toutUTF8,'',cp_UTF8);//适用于 XE2 及更高版本重写(toutUTF8);WriteLn(toutUTF8,'АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѴ');

Consider this program:

{$APPTYPE CONSOLE}

begin
  Writeln('АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ');
end.

The output on my console which uses the Consolas font is:

????????Z??????????????????????????????????????

The Windows console is quite capable of supporting Unicode as evidenced by this program:

{$APPTYPE CONSOLE}

uses
  Winapi.Windows;

const
  Text = 'АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ';

var
  NumWritten: DWORD;

begin
  WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), PChar(Text), Length(Text), NumWritten, nil);
end.

for which the output is:

АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ

Can Writeln be persuaded to respect Unicode, or is it inherently crippled?

解决方案

Just set the console output codepage through the SetConsoleOutputCP() routine with codepage cp_UTF8.

program Project1;

{$APPTYPE CONSOLE}

uses
  System.SysUtils,Windows;
Const
  Text =  'АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ';
VAR
  NumWritten: DWORD;
begin
  ReadLn;  // Make sure Consolas font is selected
  try
    WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), PChar(Text), Length(Text), NumWritten, nil);    
    SetConsoleOutputCP(CP_UTF8);
    WriteLn;
    WriteLn('АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ');
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  ReadLn;
end.

Outputs:

АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ
АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ

WriteLn() translates Unicode UTF16 strings to the selected output codepage (cp_UTF8) internally.


Update:

The above works in Delphi-XE2 and above. In Delphi-XE you need an explicit conversion to UTF-8 to make it work properly.

WriteLn(UTF8String('АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ'));


Addendum:

If an output to the console is done in another codepage before calling SetConsoleOutputCP(cp_UTF8), the OS will not correctly output text in utf-8. This can be fixed by closing/reopening the stdout handler.

Another option is to declare a new text output handler for utf-8.

var
  toutUTF8: TextFile;
...
SetConsoleOutputCP(CP_UTF8);
AssignFile(toutUTF8,'',cp_UTF8);  // Works in XE2 and above
Rewrite(toutUTF8);
WriteLn(toutUTF8,'АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ');

这篇关于Writeln 是否能够支持 Unicode?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆