我有例如AnsiChar“A”,我想将它转换为widechar(没有进行类型转换!)。我正在考虑一些内存操作,但我不知道AnsiChar在WideChar(在内存中)的样子。也许还有一个WinAPI命令?
答案 0 :(得分:13)
类型转换有什么问题?
如果你这样做,它会起作用,但我会告诉你为什么这篇文章的内容是错误的。 :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与将字节分配给Word基本相同。没有真正的转换。碰巧的是,不仅UTF-16的第一个“基本拉丁”平面与ASCII匹配,而且第二个'Latin1补充平面'与西欧人在ANSI表中的ISO 8859-1字符集相匹配。因此,我可以通过在现有字符之间添加值0
的字节来将我的所有文本迁移到WideCharacters。
但并非所有人都幸运。如果您在Ansi中有俄语文本,则此类型转换将无效。要做到这一点,请确保您拥有Delphi 2009或更高版本,它支持unicode字符串,并具有各种工具来在编码之间以及各种ANSI代码页之间进行转换。
顺便说一下,对于AnsiChar到WideChar,你需要一个类型转换,毕竟这是一个普通的整数赋值,但你实际上可以将一个AnsiString分配给一个WideString,Delphi会为你隐藏所有的转换,并实际编译它拨打_WStrFromLStr
的电话,System
单位定义{{1}},以便您调查其工作原理。
我希望这可以回答您的具体问题,但您仍然可以阅读The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)。这是对unicode的一个非常好的解释。在其中,你会发现我提到的Ansi,ASCII和UCS-2,但所有这些都放在更多的背景中。
答案 1 :(得分:8)
提供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(Koren)等字符集是双字节字符集。您的整个方法和上面的代码都会破坏这些代码页。