【发布时间】:2010-04-01 00:12:32
【问题描述】:
我正在将 D2006 程序转换为 D2010。我有一个值存储在数据库中每个字符串的单个字节中,我需要将其加载到具有 LoadFromStream 的控件中,因此我的计划是将字符串写入流并将其与 LoadFromStream 一起使用。但它没有用。在研究这个问题时,我看到一个问题告诉我我并不真正理解从 AnsiString 到 Unicode 字符串的转换是如何工作的。这是一段独立的代码,说明了我感到困惑的问题:;
procedure TForm1.Button1Click(Sender: TObject); {$O-}
var
sBuffer: String;
oStringStream: TStringStream;
sAnsiString: AnsiString;
sUnicodeString: String;
iSize1,
iSize2: Word;
begin
sAnsiString := '12345';
oStringStream := TStringStream.Create(sBuffer);
sUnicodeString := sAnsiString;
iSize1 := StringElementSize(sAnsiString);
iSize2 := StringElementSize(sUnicodeString);
oStringStream.WriteString(sUnicodeString);
end;
如果你在最后一行中断,并检查 oStringStream 的 Bytes 属性,你会看到它看起来像这样:
Bytes (49 {$31}, 50 {$32}, 51 {$33}, 52 {$34}, 53 {$35}
我期待它可能看起来像
(49 {$31}, 00 {$00}, 50 {$32}, 00 {$00}, 51 {$33}, 00 {$00},
52 {$34}, 00 {$00}, 53 {$35}, 00 {$00} ...
显然我的期望是错误的。但是,如何将 AnsiString 转换为 unicode?
我没有从 LoadFromStream 中得到正确的结果,因为它一次从流中读取两个字节,但它接收的数据不是这样排列的。我应该怎么做才能给 LoadFromStream 一个基于 unicode 字符串的格式良好的数据流?
感谢您的帮助。
【问题讨论】:
-
我认为问题中没有足够的信息来提供有意义的答案。涉及的变量是什么类型?就编译器生成的代码中触发的任何自动转换而言,这将具有潜在的意义。还特别是 oPayGrid 的类型是什么?此对象上存在 sStream 属性表明它不是标准的 VCL 流。理想情况下,我希望看到问题中的代码示例被重新设计/扩展为一个独立的工作示例,无需进一步解释/预测即可演示该行为。
-
向奥特罗瓦致敬!对不起。我试图避免用无益的细节使问题变得混乱。我想我太成功了。 oPaygrid 是一个类(TObject)。 oPaygrid.sStream 是一个名称不佳的 AnsiString。 sUnicodeString 是一个 Delphi 字符串,默认情况下是一个 unicode 字符串。 iSize1 和 iSize2 是整数。我的问题主要是概念性的。当 AnsiString 被转换为 unicode 字符串时,我是否应该期望在 unicode 字符串中看到每个字符两个字节?我没有看到,这似乎是让我无法使用 LoadFromStream 成功加载控件的原因。
-
你不应该使用 StringElementSize()。仅当您的代码从半迁移的 C++Builder 模块调用时才需要。赋值
sUnicodeString := sAnsiString将字符串的有效负载更正为 Char=WideChar,因此对 StringElementSize 的调用将始终为您的 AnsiString 返回 SizeOf(AnsiChar),为您的 UnicodeString 返回 SizeOf(Char)。 SizeOf(AnsiChar)/SizeOf(Char) 也更快,更容易阅读和理解,并且写起来更短。 -
我将 StringElementSize 放入只是为了进行健全性检查,以确保我不会完全不期望看到一个 unicode 字符串格式化为每个字符两个字节。
-
感谢大家的帮助。 Serg 提供的代码使解决方案变得清晰。虽然我向 unicode 的迁移基本上很容易,但仍有一些事情需要额外的学习和工作。再次感谢。
标签: delphi unicode encoding delphi-2010