【问题标题】:D2009 TStringlist ansistringD2009 TStringlist ansistring
【发布时间】:2009-07-13 14:50:39
【问题描述】:

夏天的商业平静已经开始,所以我开始迁移到 D2009。我大致确定了程序的每个子系统是否应该保持ascii,或者可以是unicode,并开始移植。

一切顺利,所有组件都存在于 D2009 版本中(有些组件,例如 VSTView,虽然有点不兼容)但我现在遇到了一个问题,在某些必须保持 ansistring 的部分,我广泛使用 TStringList,主要作为基本地图。

是否已经有一些容易替换的东西,或者我应该简单地包含一个基于旧 Delphi 或 FPC 源的缩减 ansistring tstringlist?

我无法想象我是第一个遇到这种情况的人?

更改必须相对本地化,以便在我通过验证轨迹时代码仍可与 BDS2006 编译。这里有几个ifdef,没有问题。 当然 string->ansistring 和 char ->ansichar 等在我的源代码中不算作修改,因为无论如何我都必须这样做,而且它是完全向后兼容的。

编辑:我已经能够处理阅读器/编写器类中的一些内容。这使得梅森的解决方案比我最初想象的更容易。我会记住 Gabr 的建议作为后备。

泛型几乎是我购买 D2009 的原因。可惜他们让 FPC 不兼容

【问题讨论】:

  • 您是否进行了大量计算,包括字符串的字节数和字符串的长度?因为这是我做出这种降级的唯一真正要求。
  • 一个是肯定的,版本化向后兼容的二进制版本。另一个(我还没有开始)是定制的 Sax 和 DOM 实现。但主要原因是我不想向客户解释如何使用记事本和 excel 打开 unicode 文本文件等,并让它变得陈旧,陈旧。
  • 我再次对用户在 SO 上的行为感到困惑。 5 位用户对这个问题提供了深思熟虑的答案,到目前为止,71 位观众至少有 14 人投了赞成票,但没有人对这个问题投了赞成票。没有问题是完美的,但我发现阅读 Q 和 As 很有帮助 - 所以 +1 来自我。恕我直言,支持 Delphi 包括支持有关该主题的信息性讨论。

标签: delphi string unicode delphi-2009


【解决方案1】:

JCL 在 JclAnsiStrings 单元中实现了 TAnsiStrings 和 TAnsiStringList。

【讨论】:

    【解决方案2】:

    如果“map”是指“哈希表”,则可以将其替换为通用 TDictionary。尝试声明如下内容:

    uses
      Generics.Collections;
    
    type
      TStringMap<T: class> = TDictionary<ansiString, T>;
    

    然后只需将您的 StringLists 替换为正确对象类型的 TStringMaps。 (更好的类型安全被免费抛出。)此外,如果您希望字典拥有对象并在完成后释放它们,请将其更改为 TObjectDictionary 并在调用构造函数时将 [doOwnsValues] 传递给适当的参数。

    (顺便说一句,如果您要使用 TDictionary,请确保下载 D2009 Update 3。原始版本在 TDictionary 中有一些严重的错误,使其几乎无法使用。)

    编辑:如果它仍然必须在 D2006 下编译,那么你将不得不稍微调整一下。试试这样的:

    type
      TStringMap =
    {$IFDEF UNICODE}
        class TDictionary<ansiString, TObject>
        (Add some basic wrapper functions here.)
        end;
    {$ELSE}
        TStringList;
    {$ENDIF}
    

    如果您首先将包装器用作地图,则包装器不应该花费太多工作。您失去了额外的类型安全性以换取向后兼容性,但您获得了一个真正的哈希表,它在 O(1) 时间内进行查找。

    【讨论】:

    • 代码必须继续使用 D2006 编译...但也许一个小的包装器就可以了,afaik 我有最新的更新,因为它是一个月前的电子软件交付版本。 (除了我手动安装的help update 3)
    • 同时玩了一点,但TDictionary似乎不支持重复。
    【解决方案3】:

    TStringList.LoadFromFile/SaveToFile 还带有一个 TEncoding 类型的可选参数,它允许您使用 TStringList 来存储您想要的任何类型的字符串。

    procedure LoadFromFile(const FileName: string; Encoding: TEncoding); overload; virtual;
    procedure SaveToFile(const FileName: string; Encoding: TEncoding); overload; virtual;
    

    另请注意,默认情况下,TStringList 使用 ANSI 作为代码页,因此所有现有代码都可以正常工作。

    【讨论】:

    • (这一行有些滞后)如前所述,我使用 tstringlist 作为基本 MAP,所以我没有通过这些方法进行流式传输,因为所有行都有关联的对象[]
    【解决方案4】:

    这些子系统是否需要保持 ansistring,或者只是它们与外界通信的方式(RS232、文本文件等...)?就像我对 C# 所做的那样,我将 Delphi 2009 中的字符串视为字符串,并且只在其他人需要它们时才担心转换。

    这也有助于避免代码中和调用 Windows API 方法时的无意隐式转换,从而提高性能。

    【讨论】:

    • 文本文件,RS232 就在现场。然而,持久性不仅仅是 stringlist.savetostream 左右,而是具有严格的版本化向后兼容性要求的手工编码。我与您在顶层建议的大致相同,但我更愿意保留输入/输出 ansistring 的子系统并在内部大量使用它们,ansistring 以避免麻烦。后来,在迁移后,我将选定的更新为 ansistring。
    • 您应该编辑您的问题以提及与以前的 Delphi 版本的兼容性。
    • ... 显然是 unicodestring。大约一半的文件类型是二进制的。
    【解决方案5】:

    您可以修改 Delphi 2007(或更早版本)的 TStrings 和 TStringList 类并将它们重命名为 TAnsiStrings 和 TAnsiStringList。您应该会发现这是一个非常简单的修改,并且会为您提供所需的类。

    【讨论】:

    • 我在 AnsiStrings.pas 或源目录搜索中都没有看到这些。
    • ansistrings 似乎不包括 tansistringlist。整个 src/ 目录没有 grep 吗?这正是我所希望的
    • 对不起,对不起,对不起。我错了。这是一个不包含在 Delphi 2009 中的修改,但很容易做到。我会更新我的答案。
    猜你喜欢
    • 2015-08-17
    • 2018-10-12
    • 1970-01-01
    • 1970-01-01
    • 2020-12-09
    • 2021-06-05
    • 2018-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多