Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 如何将AnsiChar转换为WideChar?_String_Delphi_Winapi_Unicode - Fatal编程技术网

String 如何将AnsiChar转换为WideChar?

String 如何将AnsiChar转换为WideChar?,string,delphi,winapi,unicode,String,Delphi,Winapi,Unicode,例如,我有AnsiChar A,我想将其转换为widechar,而不必进行类型转换!。我在考虑一些内存操作,但我不知道AnsiChar在WideChar内存中会是什么样子。可能还有一个WinAPI命令?类型转换有什么问题 如果你这样做,它会起作用,但我会告诉你为什么在这篇文章的后面它是错误的p var A: AnsiChar; B: WideChar; begin A := 'a'; B := WideChar(A); 关于ANSI、ASCII和UCS-2 AnsiChars是

例如,我有AnsiChar A,我想将其转换为widechar,而不必进行类型转换!。我在考虑一些内存操作,但我不知道AnsiChar在WideChar内存中会是什么样子。可能还有一个WinAPI命令?

类型转换有什么问题

如果你这样做,它会起作用,但我会告诉你为什么在这篇文章的后面它是错误的p

var
  A: AnsiChar;
  B: WideChar;
begin
  A := 'a';
  B := WideChar(A);
关于ANSI、ASCII和UCS-2

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

这意味着,对于前127个ANSI字符(ASCII字符集),包含大多数通俗英语字符的字符几乎相同,只是它是2字节而不是1字节。所以大写字母“A”在ASCII中的字节值为$40十六进制,变成了字节$00+40作为WideChar。他们只是零填充

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

关于排版

也就是说,我可以在上面的代码片段中添加一个é,但它仍然可以正常工作。Delphi实际上只是将字节值转换为双字节值,因此将AnsiChar类型转换为WideChar基本上与将字节分配给单词相同。没有真正的转换。碰巧的是,UTF-16的第一个“基本拉丁”平面不仅与ASCII匹配,而且第二个“拉丁1补充平面”也与西欧国家国家标准协会(ANSI)表格中的ISO 8859-1字符集匹配。因此,我可以通过在现有字符之间添加值为0的字节,将所有文本迁移到WideCharacters

但并非所有人都这么幸运。如果您有Ansi的俄语文本,则此类型转换将不起作用。要正确地做到这一点,请确保您有Delphi2009或更高版本,它支持unicode字符串,并有各种工具在编码之间和各种ANSI代码页之间进行转换

B.t.w.,对于AnsiChar到WideChar,您需要一个类型转换,这毕竟是一个普通的整数赋值,但您可以实际将AnsiString赋值给WideString,Delphi将为您隐藏所有转换,并实际将其编译为对_WStrFromLStr的调用,这是在系统单元中定义的,以防您想调查它是如何工作的


我希望这能回答你的具体问题,但你还是想看看。一般来说,这是对unicode的一个很好的解释。在其中,您可以找到我提到的Ansi、ASCII和UCS-2,但它们都放在更大的上下文中。

提供了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韩文等,它们是双字节字符集。您的整个方法,以及上面的代码,在这些代码页中都出现了故障。

@BenjaminWeiss我相信大多数(如果不是所有的话)8位ANSI字符的前面都是0字节。因此,如果8位ANSI字符代码是$3E,那么WideChar Unicode值是$003E。这就是你指的吗?@BenjaminWeiss添加了一小段文字,并做了一些解释。+1。写得非常好-这就澄清了我心中还有很多其他问题。我看了一下当你将AnsiChar输入到WideChar时会发生什么,以及当你将AnsiString分配到WideString时会发生什么。事实证明它们是完全不同的,我已经添加了一段关于它的内容。一个字节确实指的是ANSI字符集中的一个字符。代码页932和949是代码页,但实际上不是ANSI代码页,尽管人们倾向于这样称呼它们。微软确实发明了一些双字节字符代码页,以适应当时只有单字节的操作系统,但这些代码页确实需要不同的处理方法。@GolezTrol没有一个Windows ANSI代码页实际上是ANSI标准。Windows 1252也不是ANSI。它们在Windows上被称为ANSI,这就是 我的意思是。Windows ANSI代码页可以也确实具有双字节字符。