我正在编写一个将宽字符串保存到二进制文件的类。我正在使用Delphi 2005,但该应用程序稍后将被移植到Delphi 2010.我在这里感到非常不确定,有人可以证实:
Delphi 2005 WideString
与完全与Delphi 2010相同<{1}}
Delphi 2005 String
char以及Delphi 2010 WideString
char保证始终大小为2个字节。
对于所有的Unicode格式,我不希望被我的字符串中的一个字符突然变为3字节宽或类似的东西。
编辑:发现这个:“我确实说过UnicodeString,而不是WideString.WideString仍然存在,并且没有变化.WideString由Windows内存管理器分配,应该用于交互使用COM对象.WideString直接映射到COM中的BSTR类型。“ at http://www.micro-isv.asia/2008/08/get-ready-for-delphi-2009-and-unicode/
现在我更加困惑了。那么Delphi 2010 String
与Delphi 2005 WideString
不一样?我应该使用WideString
吗?
编辑2: Delphi 2005中没有UnicodeString
类型.FML。
答案 0 :(得分:12)
对于您的第一个问题:WideString
与D2010的字符串的类型不完全相同。 WideString与其一直以来的COM BSTR类型相同。它由Windows管理,没有引用计数,因此每次将它传递到某处时它都会复制整个BSTR。
UnicodeString
,这是D2009中默认的字符串类型,基本上是我们都知道和喜爱的AnsiString
的UTF-16版本。它有一个引用计数,由Delphi编译器管理。
对于第二个,默认的char
类型现在为WideChar
,这些字符与WideString
中始终使用的字符相同。它是UTF-16编码,每个字符2个字节。如果将WideString数据保存到文件,则可以毫无困难地将其加载到UnicodeString
。这两种类型之间的区别与内存管理有关,而不是数据格式。
答案 1 :(得分:4)
正如其他人提到的,Delphi 2009及更高版本中的字符串(实际上是UnicodeString)数据类型不等同于以前版本中的WideString数据类型,但数据内容格式是相同的。它们都以UTF-16保存字符串。因此,如果您在早期版本的Delphi中使用WideString保存文本,您应该能够在最近版本的Delphi(2009及更高版本)中使用字符串数据类型正确读取它。
您应该注意UnicodeString的性能优于WideString。因此,如果您要在Delphi 2005和Delphi 2010中使用相同的源代码,我建议您在代码中使用带有条件编译的字符串类型别名,这样您就可以充分利用这两个世界:
type
{$IFDEF Unicode}
MyStringType = UnicodeString;
{$ELSE}
MyStringType = WideString;
{$ENDIF}
现在,您可以在源代码中使用MyStringType作为字符串类型。如果编译器是Unicode(Delphi 2009及更高版本),那么您的字符串类型将是UnicodeString类型的别名,它在Delphi 2009中引入以保存Unicode字符串。如果编译器不是unicode(例如Delphi 2005),那么您的字符串类型将是旧WideString数据类型的别名。由于它们都是UTF-16,任何版本保存的数据都应该由另一个版本正确读取。
答案 2 :(得分:1)
事实并非如此 - ex Delphi 2010字符串隐藏了内部代码页字段 - 但可能对您无关紧要。
这是事实。在Delphi 2010中,SizeOf(Char)= 2(Char = WideChar)。
unicode字符串不能有不同的代码页 - 引入代码页字段为Ansi字符串(需要代码页字段)和Unicode字符串(不需要它)创建通用二进制格式。
如果在Delphi 2005中将WideString数据保存到流中并在Delphi 2010中将相同的数据加载到字符串中,则一切正常。
WideString = BSTR,并且在Delphi 2005和2010之间没有改变
UnicodeString = Delphi 2005中的WideString(如果Delphi 2005中存在UnicodeString类型 - 我不知道) Delphi 2009及更高版本中的UnicodeString = string。
@Marco - Delphi 2009+中的Ansi和Unicode字符串具有通用的二进制格式(12字节标题)。
UnicodeString代码页CP_UTF16 = 1200;
答案 3 :(得分:0)
规则很简单:
UnicodeString
类型(*)。WideString
类型。你看,WideString
是一种特殊的类型,因为它不是原生的Delphi类型。它是BSTR
的别名/包装器 - 系统字符串类型,用于与COM或跨模块通信一起使用。作为一个unicode - 只是一个副作用。
另一方面,AnsiString
和UnicodeString
- 是本机Delphi类型,在其他语言中没有模拟。 String
只是AnsiString
或UnicodeString
的别名。
因此,如果您需要将字符串传递给其他代码 - 请使用WideString
,否则 - 使用AnsiString
或UnicodeString
。简单。
P.S。
(*)对于旧的德尔福 - 只是放置
{$IFNDEF Unicode}
type
UnicodeString = WideString;
{$ENDIF}
代码中的某处。此修复程序将允许您为任何Delphi版本编写相同的代码。
答案 4 :(得分:0)
虽然D2010字符始终是2个字节,但UTF-16字符中存在相同的字符折叠和组合问题,如UTF-8字符。你没有看到这个用窄字符串,因为它们是基于代码页的,但是使用unicode字符串,有可能(在某些情况下常见)有情感但不可见的字符。示例包括unicode文件或流的开头的字节顺序标记(BOM),从左到右/从右到左的指示符字符,以及大量的组合重音。这主要影响“这个字符串在屏幕上会有多少像素宽度”和“此字符串中有多少个字母”的问题(与“此字符串中有多少个字符”不同),但也意味着你可以' t随机地从字符串中删除字符并假设它们是可打印的。像“删除这个单词的最后一个字母”之类的操作变得非常重要,取决于使用的语言。
关于“我的字符串中的一个字符突然变成3个字节长”的问题反映了对UTF如何工作的一点关注。可以(并且有效)在UTF-8字符串中使用三个字节来表示一个可打印字符,但每个字节将是一个有效的UTF-8字符。说,一封信加上两个组合口音。如果使用UTF-16或UTF-32中的三个代码点表示UTF-16或UTF-32长度为3个字节,则不会得到6个字节(或12个字节)长的字符。这使我们正常化(或不)。
但是如果您只处理字符串作为整个事情,那就非常简单 - 您只需将字符串写入文件,然后再读回来。您不必担心细则字符串显示和操作,这些都由操作系统和库处理。 Strings.LoadFromFile(name)和Listbox.Items.Add(string)在D2010中的工作方式与在D2007中完全相同,unicode的东西对程序员来说都是透明的。
答案 5 :(得分:0)
我正在编写一个将宽字符串保存到二进制文件的类。
在D2005中编写课程时,您将使用Widestring 当您迁移到D2010时,Widestring仍然有效且工作正常。 D2005中的Widestring与D2010中的WideString相同。
由于编译器很容易处理这些问题,因此无需考虑D2010中String = WideString的事实。
使用(AString:String)保存的输入例程只需要一行输入proc
procedure SaveAStringToBIN_File(AString:String);
var wkstr : Widestring;
begin
{$IFDEF Unicode} wkstr := AString;
{$ELSE} wkstr := UTF8Decode(AString); {$ENDIF}
...
the rest is the same saving a widestring to a file stream
write the length (word) of string then data
end;