例如,我有一个AnsiChar "A“,我想把它转换成一个宽字符串(不需要进行类型转换!)。我在考虑一些内存操作,但我不知道在WideChar中(在内存中) AnsiChar会是什么样子。也许还有一个WinAPI命令?
发布于 2013-06-30 07:00:36
类型转换有什么问题?
如果你这样做了,它是有效的,但我会在这篇文章的后面告诉你为什么它是错误的。:p
var
A: AnsiChar;
B: WideChar;
begin
A := 'a';
B := WideChar(A);关于ANSI和ASCII (和UCS-2)
AnsiChars是单字节字符。WideChars是使用UCS-2编码的双字节字符,它是UTF-16的子集。
这意味着对于前127个ANSI字符(这是ASCII字符集,包含大多数通俗易懂的字符)几乎相同,只是它是2个字节而不是1个字节。因此,在ASCII码中具有$40 (十六进制)字节值的大写'A‘变成字节$00 + $40作为WideChar。它们只是零填充的。
对于ANSI集合的上半部分,这并不容易,因为这些字符可能具有不同的含义,具体取决于所使用的代码页。此范围可以包含希腊字符、西欧字符(如é)或其他字符,但不能包含所有字符的组合,因为在该范围内只能容纳128个字符。因此,要将ANSI转换为WideChar,您必须知道(或假定)代码页。所有(或大部分)代码页在widechar支持的65536个不同字符的总范围内具有不同的位置。
关于类型转换的
也就是说,我可以在上面的代码片段中添加一个é,它仍然可以意外地工作。Delphi实际上只是将字节值转换为双字节值,因此将AnsiChar类型转换为WideChar基本上与将Byte值赋给Word相同。没有完成真正的转换。碰巧的是,不仅UTF-16的第一个“基本拉丁语”平面与ASCII匹配,而且第二个“Latin1补充平面”也与西欧人的ANSI表中的ISO8859-1字符集匹配。因此,我只需在现有字符之间添加值为0的字节,就可以将所有文本迁移到WideCharacters。
但并不是所有的人都这么幸运。如果你有一个俄语文本在Ansi中,那么这个类型转换将不起作用。要正确地做到这一点,请确保您有Delphi 2009或更高版本,它支持unicode字符串,并具有各种工具来在编码之间和各种ANSI代码页之间进行转换。
B.t.w.,对于AnsiChar到WideChar,你需要一个类型转换,这毕竟是一个普通的整数赋值,但你实际上可以将一个AnsiString赋给一个WideString,Delphi会为你隐藏所有的转换,并实际上将其编译为对_WStrFromLStr的调用,这是在System单元中定义的,以防你想要研究它是如何工作的。
我希望这能回答您的具体问题,但是您可能想要阅读The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)。总的来说,这是对unicode的一个很好的解释。在其中,您可以找到我提到的Ansi、ASCII和UCS-2,但它们都放在更多的上下文中。
发布于 2013-06-30 15:53:53
提供了Windows API函数MultiByteToWideChar来执行此转换。当然,您需要指定输入数据的代码页。例如:
function AnsiCharToWideChar(ac: AnsiChar; CodePage: UINT): WideChar;
begin
if MultiByteToWideChar(CodePage, 0, @ac, 1, @Result, 1) <> 1 then
RaiseLastOSError;
end;请注意,ANSI代码页中定义的所有字符都映射到基本多语言平面中的Unicode字符,因此由单个UTF-16字符表示。因此,上面代码的大小假设。
但是,您所做的假设是,单个字节表示ANSI字符集中的一个字符。对于许多字符集来说,这是一个有效的假设,例如像1252这样的单字节西部字符集。但是像932 (日语)、949 (朝鲜语)等字符集是双字节字符集。对于这些代码页,您的整个方法和上面的代码都被分解了。
https://stackoverflow.com/questions/17385456
复制相似问题