【问题标题】:Which takes the biggest hit: AnsiString to String or String to AnsiString?哪个受到最大的打击:AnsiString 到 String 或 String 到 AnsiString?
【发布时间】:2011-10-13 18:19:54
【问题描述】:

出于我的目的,我实际上是在真正使用 ASCII 字符数据(用于向州提交 ASCII 文本文件),因此仅使用 unicodestring 无助于最终结果(我仍然需要转换一些东西)。

我可以选择在 Delphi 2009 中转换 StrComp 函数,该函数从比较 AnsiString 和 PAnsiChar 到 UnicodeString 和 PAnsiChar。

Val : PAnsiChar
Mask : TEditMask;

....

这是我原来的代码,不好

StrComp(PAnsiChar(Mask.EditText), Val);

....

所以,我可以改成这样:

StrComp(PAnsiChar(AnsiString(MAskEdit.EditText), Val);

或者,我可以将其更改为这个(“清晰度”的额外转换):

StrComp(PChar(MAskEdit.EditText), PChar(String(AnsiString(Val))));

我记得 Marco Cantu 说过,不要循环执行其中一项,我只是不记得是哪一项或为什么。

【问题讨论】:

  • 您可以像 VCL AnsiStrings 单元一样从 kernel32 调用 CompareStringA(从 Windows.pas 获取它)。然后你必须从 Unicode 到 Ansi 进行 1 次转换。这真的是瓶颈吗?
  • 最大的问题似乎是当你不断追加到一个不断增长的字符串时。阿拉UnicodeStr := ANSIStr + UnicodeStr。我只是不知道这在 CPU 上是否比ANSISTr := UnicodeStr + AnsiStr 更容易。没关系是一个完全可以接受的答案。
  • 为此使用 StringBuilder。这个问题是关于堆分配的。尽量减少转换。所以在不转换的情况下构建字符串,然后在最后阶段进行转换。
  • 似乎很容易自己测试。但是你有没有注意到任何糟糕的性能以至于值得你去修改你的代码?
  • @Rob 还没有完成所有 292 个错误和警告。我自己写测试可能会自己回答。

标签: delphi unicode delphi-2009


【解决方案1】:

如果你编译这个:

StrComp(PAnsiChar(Mask.EditText), Val);

为了允许类型转换为PAnsiChar,存在从Mask.EditTextUnicodeString 到临时AnsiString 的隐式转换。那是你的第二行:

StrComp(PAnsiChar(AnsiString(MAskEdit.EditText), Val);

但是写

StrComp(PChar(MAskEdit.EditText), PChar(String(AnsiString(Val))));

会让PChar(MAskEdit.EditText)返回一个PChar,也就是一个PWideChar,所以它会使用另一个重载的StrComp函数。

事实上,从 Delphi 2009 开始在 SysUtils.pas 中定义了两个重载函数:

function StrComp(const Str1, Str2: PAnsiChar): Integer; overload;
function StrComp(const Str1, Str2: PWideChar): Integer; overload;

这两个函数都不会调用windows API,而是会一一比较字符,区分大小写。

所以我的建议是,您根本不要在代码中使用任何指针,而是在代码中的任何地方都使用普通的 string = UnicodeString 变量,并改用这个函数:

function CompareStr(const S1, S2: string): Integer;

比较会一样,不会有隐藏转化。与 unicode 和当前 ansi 页面之间的转换(两次 WinAPI 调用)相比,使用 WideChar 而不是 AnsiChar(即拥有两倍多的内存)的问题微不足道。引用你的标题,转化方向并不重要:它总是比没有转化慢得多。

如果您搜索速度,我怀疑Mask.EditText 肯定是您代码中的瓶颈。这个方法会发送一个 GDI 消息,等待组件的响应,然后用文本影响一个string。你最好在堆栈上使用一个临时变量,如果我怀疑你在循环中使用这个Mask.EditText 表达式。

【讨论】:

    【解决方案2】:

    真正的问题是 - 为什么要将 UnicodeStringPAnsiChar 进行比较,而不是将 PAnsiChar 数据更新为 Unicode?您应该在与遗留数据、网络连接等交互的边界处使用 AnsiChar/AnsiString。所有内部处理都应使用单个字符串编码以避免此类问题。加载数据时将遗留/网络数据从 Ansi 转换为 Unicode。在保存遗留数据、发送网络数据等时从 Unicode 转换为 Ansi。

    【讨论】:

    • 不知道为什么投反对票。 Remy 是对的:最好的做法是加载您的数据,转换为 Unicode(系统的其余部分 / RTL / VCL / everything 使用的),然后在导出时转换回来。即,将转化保持在应用的边缘。
    猜你喜欢
    • 2012-03-16
    • 2018-06-10
    • 1970-01-01
    • 2011-08-28
    • 1970-01-01
    • 1970-01-01
    • 2012-11-11
    • 2018-10-12
    相关资源
    最近更新 更多