Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/3.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 将UTF-8字符串存储在Unicode解构中_String_Delphi_Unicode_Utf 8_Utf 16 - Fatal编程技术网

String 将UTF-8字符串存储在Unicode解构中

String 将UTF-8字符串存储在Unicode解构中,string,delphi,unicode,utf-8,utf-16,String,Delphi,Unicode,Utf 8,Utf 16,在Delphi2007中,您可以将UTF-8字符串存储在WideString中,然后将其传递到Win32函数,例如 var UnicodeStr: WideString; UTF8Str: WideString; begin UnicodeStr:='some unicode text'; UTF8Str:=UTF8Encode(UnicodeStr); Windows.SomeFunction(PWideChar(UTF8Str), ...) end; Delphi 20

在Delphi2007中,您可以将UTF-8字符串存储在WideString中,然后将其传递到Win32函数,例如

var
  UnicodeStr: WideString;
  UTF8Str: WideString;
begin
  UnicodeStr:='some unicode text';
  UTF8Str:=UTF8Encode(UnicodeStr);
  Windows.SomeFunction(PWideChar(UTF8Str), ...)
end;
Delphi 2007不会干扰UTF8Str的内容,即它作为UTF-8编码字符串保存在WideString中

但在Delphi2010中,我正在努力找到一种方法来做同样的事情,即将UTF-8编码的字符串存储在WideString中,而不会自动从UTF-8转换。我无法传递指向UTF-8字符串(或RawByteString)的指针,例如,以下操作显然不起作用:

var
  UnicodeStr: WideString;
  UTF8Str: UTF8String;
begin
  UnicodeStr:='some unicode text';
  UTF8Str:=UTF8Encode(UnicodeStr);
  Windows.SomeFunction(PWideChar(UTF8Str), ...)
end;

哪个Windows API调用希望您传递UTF-8字符串?它是ANSI字符串或Widestring(a或W函数)。宽字符串每个字符有两个字节,UTF-8字符串有一个字节(如果超出前128个ASCII字符,则有多个字节)


宽字符串中的UTF-8根本没有意义。当确实有一个Windows函数需要一个指向UTF-8字符串的指针时,您可能需要将is转换为PAnsiChar。

嗯,为什么要这样做?为什么将WideString编码为UTF-8只是为了将其再次存储回WideString。显然,您使用的是Unicode版本的Windows API。因此,不需要使用UTF-8编码的字符串。还是我遗漏了什么

因为Windows API函数是Unicode(两个字节)或ANSI(一个字节)。UTF-8在这里的选择是错误的,因为它主要是每个字符包含一个字节,但对于ASCII基以上的字符,它使用两个或更多字节

否则,unicode Delphi中旧代码的等效值为:

var
  UnicodeStr: string;
  UTF8Str: string;
begin
  UnicodeStr:='some unicode text';
  UTF8Str:=UTF8Encode(UnicodeStr);
  Windows.SomeFunction(PWideChar(UTF8Str), ...)
end;
WideString和string(UnicodeString)类似,但是新的UnicodeString更快,因为它是引用计数的,而WideString不是

您的代码不正确,因为UTF-8字符串每个字符的字节数可变。“A”存储为一个字节。只是一个ASCII字节码。另一方面,“ü”将存储为两个字节。因为您使用的是PWideChar,所以函数总是希望每个字符有两个字节

还有一个区别。在旧的Delphi版本(ANSI)中,Utf8String只是一个AnsiString。在Delphi的Unicode版本中,Utf8String是一个后面带有UTF-8代码页的字符串。所以它的行为不同

旧代码仍然可以正常工作:

var
  UnicodeStr: WideString;
  UTF8Str: WideString;
begin
  UnicodeStr:='some unicode text';
  UTF8Str:=UTF8Encode(UnicodeStr);
  Windows.SomeFunction(PWideChar(UTF8Str), ...)
end;
它的行为将与Delphi 2007中的相同。也许你在别的地方遇到了问题

米克,你说得对。编译器在幕后做一些额外的工作。所以为了避免这种情况,你可以这样做:

var
  UTF8Str: AnsiString;
  UnicodeStr: WideString;
  TempString: RawByteString;
  ResultString: WideString;
begin
  UnicodeStr := 'some unicode text';
  TempString := UTF8Encode(UnicodeStr);
  SetLength(UTF8Str, Length(TempString));
  Move(TempString[1], UTF8Str[1], Length(UTF8Str));
  ResultString := UTF8Str;
end;

我检查了一下,结果还是一样。因为我直接在内存中移动字节,所以没有在后台进行代码页转换。我相信这可以用greater eleganece实现,但重点是我认为这是实现您想要实现的目标的途径。

您最初的Delphi 2007代码使用ANSI代码页将UTF-8字符串转换为宽字符串。要在Delphi2010中执行相同的操作,您应该使用带有Convert参数false的SetCodePage

var
  UnicodeStr: UnicodeString;
  UTF8Str: RawByteString;
begin
  UTF8Str := UTF8Encode('some unicode text');
  SetCodePage(UTF8Str, 0, False);
  UnicodeStr := UTF8Str;
  Windows.SomeFunction(PWideChar(UnicodeStr), ...)

这是一些使用INI文件的(损坏的)遗留代码。例如,该节将作为UTF8字符串传递。我知道这是错误的,但我需要保持这样导入旧设置文件。如果我传递Unicode作为节名,那么它将不匹配。我不能使用ANSI版本,因为文件名是Unicode。我用解决方案更新了我的答案。仅供参考,原始2007代码确实会干扰UTF-8数据。2007年,
UTF8Encode()。在每个版本中,将
ansisting
分配给
WideString
使用操作系统默认的Ansi代码页执行Ansi->UTF16转换。最后的
WideString
中不包含UTF-8数据。它包含UTF-16数据。转换没有UTF-8存在的概念,因此如果原始输入使用任何非ASCII字符,可能会损坏数据。Nice。不知道:)是的,在将temp
ansisting
分配给最终的
WideString
时,在最后一行进行了代码页转换。在最初的D2007代码中也是如此。但另一方面,您可以通过在
RawByteString
上使用
SetCodePage()
来避免临时
AnsiString
,然后您可以将
RawByteString
分配给
WideString