【问题标题】:Delphi XE - should I use String or AnsiString?Delphi XE - 我应该使用 String 还是 AnsiString?
【发布时间】:2011-08-28 07:41:16
【问题描述】:

我终于升级到了 Delphi XE。我有一个单位库,我使用字符串来存储普通的 ANSI 字符(A 和 U 之间的字符)。我 101% 确信我永远不会在那些地方使用 UNICODE 字符。

我想将所有其他库转换为 Unicode,但对于这个特定的库,我认为坚持使用 ANSI 会更好。优点是内存要求,因为在某些情况下我加载非常大的 TXT 文件(仅包含 Ansi 字符)。缺点可能是当我使这些库与普通(unicode)库交互时,我必须进行大量的类型转换。

有一些通用指南可以说明何时最好转换为 Unicode 以及何时坚持使用 Ansi?

【问题讨论】:

    标签: delphi unicode


    【解决方案1】:

    一般准则的问题在于,此类内容可能非常具体地针对一个人的情况。您的示例就是其中之一。

    但是,对于使用谷歌搜索并到达这里的人,一些一般准则是:

    • 是的,转换为 Unicode。不要尝试完全使用AnsiStrings 来保留旧应用程序。原因是整个 VCL 都是 Unicode,你不应该尝试将两者混合,因为你每次将 Unicode 字符串分配给 ANSI 字符串时都会进行转换,这是一种有损转换。试图保留旧方法,因为它的工作量较少(或一些类似的原因)会给你带来痛苦;只需接受新的string 类型,转换并使用它。

    • 不要将两者随机混合,而是显式执行一次您需要的任何转换 - 例如,如果您从旧版本的程序加载数据,您知道它将是 ANSI,因此将其读入那里有一个Unicode字符串,就是这样。从此以后,它将是 Unicode。

    • 您不需要更改 string 变量的类型 - D2009 之前的string 是 ANSI,而在 D2009 和 alter 中是 Unicode。相反,请关注 compiler warnings 并观察您使用的字符串方法 -​​ 有些仍然采用 AnsiString 参数,我觉得这一切都令人困惑。编译器会告诉你的。

    • 如果您使用字符串来保存字节(换句话说,将它们用作字节数组,因为字符是一个字节)切换到TBytes

    • 您可能会遇到加密等特定问题(字符串不再是字节/字符,因此“字符”的“字符”可能会得到不同的输出);读取文本文件(使用流类和TEncoding);坦率地说,还有杂项。在 SO 上搜索这里,大多数事情以前都被问过。

    评论者,请多提建议...我主要使用C++Builder,而不是Delphi,对于Delphi可能有很多我不知道的具体东西。

    现在针对您的具体问题:您应该转换此库吗?

    如果:

    • A 和 U 之间的值实际上只在这个范围内,并且
    • 这些值表示字符(A 确实是 A,而不是字节值 65 - 如果是,则使用 TBytes),并且
    • 您加载大型文本文件,内存是个问题

    然后不转换为 Unicode,而是将您的 strings 切换为 AnsiStrings,这是有道理的。

    请注意:

    • 每次从 ANSI 转换为 Unicode 时都会产生开销
    • 您可以使用UTF8String,它是AnsiString 的一种特定类型,转换后不会丢失,并且仍将大部分文本(罗马字符)存储在一个字节中
    • string 的所有实例更改为AnsiString 可能需要一些工作,并且您需要检查使用它们调用的所有方法以查看是否正在执行太多隐式转换(为了性能)等
    • 您可能需要更改库的外层以使用 Unicode,以便库的用户看不到转换代码或 ANSI/Unicode 编译器警告
    • 如果转换为 Unicode,字符集(不记得语法,可能是 if 'S' in MySet?)won't work。从你对字符 A 到 U 的描述,我猜你想使用这种语法。

    我的建议?就我个人而言,根据您提供的信息,我这样做的唯一原因是内存使用情况,并且可能性能取决于您对大量 @ 所做的事情987654339@s。 如果这真的很重要,它既是驱动因素又是约束因素,您应该转换为 ANSI。

    【讨论】:

    • 谢谢大卫。我开始将此库转换为 Ansi,这很有意义。我还看到这个库和其他经典(unicode)库之间的交互并没有我担心的那么大。大多数情况下,我必须在画布上“打印”那些 A-U 字符串。太糟糕了,我之前没有使用 UTF8String 的想法。我已经开始了我的转换。但是,如果我看到问题,我会明确地考虑它。再次感谢。
    【解决方案2】:

    您应该能够在本单元与其客户端之间的接口处完成转换。在内部使用 AnsiString 并在其他任何地方使用字符串,你应该没问题。

    【讨论】:

    • @Altar - 我认为大卫总结得非常巧妙(他通常这样做)。而且我不确定如果您有精心设计的用于访问 Ansi 数据的接口,那么您为什么需要“大量的类型转换”——只需在 Ansi 和 Unicode 之间的阈值函数中使用 System.StringToWideChar ——请参阅 ms-help: //embarcadero.rs_xe/vcl/System.StringToWideChar.html XE 帮助“从 AnsiString 返回一个 UNICODE 字符串。” HTH MN
    • 我知道 - 这就是我自己所做的,我从来没有遇到过问题 - 但由于有一个记录在案的 VCL 函数,我认为它更重要...... :-)
    【解决方案3】:

    一般来说,如果 Chars 是单个字节很重要,则仅使用 AnsiString,否则使用字符串可确保将来与 Unicode 兼容。

    【讨论】:

      【解决方案4】:

      无论如何,您都需要检查所有库,因为 Delhpi XE 中的所有 Windows API 函数都被它们的 unicode-analogue 等取代。如果您永远不会使用 UNICODE,则需要使用 Delphi 7。

      【讨论】:

      • 如果您不需要 Unicode,Delphi 2007 将可以正常工作,并且更新了很多。
      • 我没有说我不使用 UNICODE(尽管它是真的,但我并不在意它)。我只对这个特定的库使用 ANSI 字符串,因为我使用缩减字母表并且我需要小字符串来减少内存需求。
      【解决方案5】:

      在本单元的任何地方都显式使用 AnsiString,然后如果您碰巧不正确地访问例程,您将收到 String 到 AnsiString 转换错误的编译器警告错误(您永远不应忽略)。

      或者,最好根据您的情况,将所有内容都转换为 UTF8。

      【讨论】:

        【解决方案6】:

        仅当您没有时间正确转换代码时才坚持使用 Ansi 字符串。 Ansi 字符串的使用实际上只是为了向后兼容——据我所知,C# 没有与 Ansi 字符串等价的字符串。否则使用标准的 Unicode 字符串。如果你看一下我的网站,我有一个完整的字符串例程单元(大约 5,000 LOC),它适用于 Delphi 2007(非 Uniocde)和 XE(Unicode),只有“字符串”接口,并且包含几乎所有的您可能会遇到的转换问题。

        【讨论】:

        • “Ansi 字符串的使用实际上只是为了向后兼容” - - - 实际上,在我的情况下是为了内存需求。 UNICODE 将使我的程序需要 2 倍以上的 RAM!这将突破当今普通(2-4GB RAM)计算机的限制。我的所有其他库都已转换为 UNICODE。
        猜你喜欢
        • 1970-01-01
        • 2011-03-20
        • 2010-11-30
        • 2019-10-19
        • 1970-01-01
        • 2018-09-05
        • 2021-11-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多