如何将AnsiChar转换为WideChar?

Ben*_*iss 0 delphi string unicode winapi

我有例如AnsiChar"A",我想将它转换为widechar(没有类型转换!).我正在考虑一些内存操作,但我不知道AnsiChar在WideChar(在内存中)的样子.也许还有一个WinAPI命令?

Gol*_*rol 13

类型转换有什么问题?

如果你这样做它会起作用,但我会告诉你为什么这篇文章的内容是错误的.:p

var
  A: AnsiChar;
  B: WideChar;
begin
  A := 'a';
  B := WideChar(A);
Run Code Online (Sandbox Code Playgroud)

关于ANSI和ASCII(和UCS-2)

AnsiChars是单字节字符.WideChars是具有UCS-2编码的双字节字符,UCS-2编码是UTF-16的子集.

这意味着对于前127个ANSI字符(这是ASCII字符集,包含大多数字符,用简单的英语知道)几乎相同,除了它是2个字节而不是1个字节.因此,以ASCII为单位的字节值为$ 40(十六进制)的大写字母'A'将成为$ 00 + $ 40作为WideChar的字节.它们只是零填充.

对于ANSI集的上半部分,这并不容易,因为这些字符可能具有不同的含义,具体取决于所使用的代码页.此范围可以包含希腊字符,西欧字符(如é)或其他字符,但不是所有字符的组合,因为在该范围内只有128个字符的空间.因此,要将ANSI转换为WideChar,您必须知道(或假设)代码页.所有(或大多数)这些代码页在widechar支持的65536个不同字符的总范围内具有不同的位置.

关于类型转换

也就是说,我可以在上面的代码片段中添加一个é,它仍然可以正常工作.Delphi实际上只是将字节值转换为双字节值,因此将AnsiChar强制转换为WideChar与将字节分配给Word基本相同.没有真正的转换.碰巧的是,不仅UTF-16的第一个"基本拉丁"平面与ASCII匹配,而且第二个'Latin1补充平面'与西欧人在ANSI表中的ISO 8859-1字符集相匹配.因此,我可以通过添加0现有字符之间的值的字节来将我的所有文本迁移到WideCharacters .

但并非所有人都幸运.如果您在Ansi中有俄语文本,则此类型转换将无效.要做到这一点,请确保您拥有Delphi 2009或更高版本,它支持unicode字符串,并具有各种工具来在编码之间和各种ANSI代码页之间进行转换.

顺便说一句,对于AnsiChar到WideChar,你需要一个类型转换,毕竟这是一个普通的整数赋值,但你实际上可以将一个AnsiString分配给一个WideString,Delphi会为你隐藏所有的转换,并实际编译它为一个调用to _WStrFromLStr,System如果您想调查它是如何工作的,则在单元中定义.

我希望这可以回答您的具体问题,但是,您仍然可以阅读绝对最低限度每个软件开发人员,绝对必须知道Unicode和字符集(没有借口!).这是对unicode的一个非常好的解释.在其中,你会发现我提到的Ansi,ASCII和UCS-2,但都放在更多的上下文中.

  • +1.写得非常好.:-) (3认同)
  • 我已经看过当你将AnsiChar强制转换为WideChar时会发生什么,以及当你将AnsiString分配给WideString时会发生什么.事实证明它们完全不同,我添加了一个关于它的段落. (2认同)

Dav*_*nan 8

提供了Windows API函数MultiByteToWideChar来执行此转换.当然,您需要指定输入数据的代码页.例如:

function AnsiCharToWideChar(ac: AnsiChar; CodePage: UINT): WideChar;
begin
  if MultiByteToWideChar(CodePage, 0, @ac, 1, @Result, 1) <> 1 then
    RaiseLastOSError;
end;
Run Code Online (Sandbox Code Playgroud)

请注意,ANSI代码页中定义的所有字符都映射到基本多语言平面中的Unicode字符,因此由单个UTF-16字符表示.因此,上面代码的大小假设.

但是,假设您正在制作并且此答案仍然存在,则单个字节表示ANSI字符集中的字符.这是许多字符集的有效假设,例如单字节西方字符集,如1252.但是有932(日语),949(Koren)等字符集是双字节字符集.您的整个方法和上面的代码都会破坏这些代码页.