【问题标题】:Is there some advantage in use resourcestring instead of a const string?使用 resourcestring 而不是 const 字符串有什么优势吗?
【发布时间】:2010-11-27 16:26:12
【问题描述】:

你能告诉我在使用中是否有一些优势(更少的存储空间,提高速度等):

resourcestring
    MsgErrInvalidInputRange = 'Invalid Message Here!';

而不是

const
    MsgErrInvalidInputRange : String = 'Invalid Message Here!';

【问题讨论】:

    标签: delphi


    【解决方案1】:

    const 选项会比 resourcestring 更快,因为后者会调用 Windows API 来获取资源文本。 您可以通过使用一些缓存机制使其更快。这就是我们在增强型 Delphi RTL 中所做的。

    如果您必须多次访问资源字符串内容,最好先将资源字符串加载到字符串中。

    resourcestring 的要点是允许你的程序进行 i18n(国际化)。

    您已经获得了带有某些版本的 Delphi IDE 的翻译管理器。但它依赖于外部 DLL。

    您可以使用来自 Linux 世界的 gettext 系统,来自 http://dxgettext.po.dk,它依赖于外部 .po 文件。

    我们在我们的框架中包含了我们自己的 i18n 机制,它翻译和缓存资源字符串文本,并依赖于外部 .txt 文件(您可以使用 UTF-8 或 Unicode 文本文件,从 Delphi 6 到 XE)。缓存使其与 const 使用一样快。见http://synopse.info/fossil/finfo?name=SQLite3/SQLite3i18n.pas

    还有其他开源或商业解决方案。

    关于大小存储,resourcestring存储为UC2缓冲区。因此,直到 Delphi 2009,resourcestring 将使用比字符串更多的内存。自 Delphi 2009 以来,所有字符串都是 unicodestring,即 UCS2,因此您不会有更多的存储空间。在所有情况下,文本的存储大小并不是应用程序更大的大小参数(位图和代码大小对最终 exe 的影响要大得多)。

    【讨论】:

    • 如果资源系统没有初始化,它会真正调用windows api吗? (iow 没有加载翻译) 没有通过 Delphi,但 FPC 没有。 dxgettext 很棒(我更喜欢它而不是 ITE),但它也有缺点,特别是 wrt 资源字符串
    • @Marco:当然,Windows API 总是被调用,即使没有加载翻译。检查 System.pas 中的 LoadResString() 过程
    【解决方案2】:

    资源字符串在您的 exe 资源中存储为 STRINGTABLE 条目,常量存储为固定数据段的一部分。由于它们是资源部分的一部分,您可以提取它们和 DFM、翻译它们并将它们存储在资源模块(仅数据 DLL)中。当一个 Delphi 应用程序启动时,它会查找该 DLL 并将使用其中的字符串而不是包含在您的 EXE 中的字符串来加载翻译。

    Embarcadero docwiki 使用 Translation Manager 进行覆盖,但许多其他 Delphi 翻译工具也使用资源字符串。

    【讨论】:

    • 资源是 Windows 下用于本地化应用程序的事实标准。翻译编辑器和其他工具也可以修改存储为资源的 .dfms。优点是不仅字符串,甚至控件的大小、位置、颜色和图像都可以根据目标“文化”进行定制,这是使用仅翻译字符串的工具无法做到的。
    • FPC 2.4.0+ 在任何地方都支持资源字符串的机制。 Lazarus afaik 尚未将其 dfm 存储在资源中,但这可能会在短期内改变,Lazarus 仍在经历 2.2->2.4 过渡
    • @ldsandon:您可以即时自定义资源字符串和 dfm,无需修改任何资源。这就是 dxgettext 和我们的单元所做的,通过挂钩一些 VCL 调用(如 LoadResString 或 TCustomForm.Create)。
    【解决方案3】:

    正如其他人所提到的,resourcestring 字符串将包含在您的 exe 中的单独资源中,因此当您需要在应用程序的 UI 中满足多种语言时,它具有优势。

    正如一些人所提到的,常量字符串包含在应用的数据部分中。

    截至 2007 年

    直到 D2007 的 Delphi 版本中,const 字符串存储为 Ansi 字符串,每个字符需要一个字节,而资源字符串将以 UTF-16 存储:Windows 默认编码(尽管可能不适用于 Win9x)。 IIRC D2007 和之前的版本不支持 UTF-8 编码的单元文件。因此,在您的源代码中编码的任何字符串都必须得到 ANSI 代码页的支持,因此可能不会超出 Unicode 基本多语言平面。这意味着将只使用 UTF-16 的 UCS-2 部分,并且所有字符串可以存储在每个字符两个字节中。

    简而言之:最多 D2007 const 字符串每个字符占用一个字节,资源字符串每个字符占用两个字节。

    D2009 及更高版本

    Delphi 在 D2009 版本中启用了 unicode。从那时起,情况就有些不同了。 Resourcesstring 字符串仍以 UTF-16 格式存储。这里没有其他选项,因为它们是由 Windows“管理”的。

    然而,Consts 字符串是一个完全不同的故事。自 D2009 以来,Delphi 将每个 const 字符串的多个版本存储在您的 exe 中。每个版本采用不同的编码。 const 可以存储为 Ansi 字符串、UTF-8 字符串和 UTF-16 字符串。

    存储哪些编码取决于 const 的使用。默认情况下将使用 UTf-16,因为这是默认的内部 Delphi 编码。将相同的 const 分配给“普通”(UTF-16)字符串以及 AnsiString 变量,该 const 将存储在 UTF-16 和 Ansi 编码的 exe 中...

    重复数据删除

    从外观上看(用 D5 和 D2009 进行实验),Delphi “de-dupes” const 字符串,而它不会对资源字符串执行此操作。

    【讨论】:

    • 重复数据删除位是合乎逻辑的。 “应用程序内置语言”中相同的两个词在翻译时可能具有多种含义,具体取决于上下文。
    • 在 MBCS(如亚洲)字符集的情况下,“每个字符一个字节”和“每个字符两个字节”是不正确的。但对于英语/西欧语言(代码页 1252),情况确实如此。在所有情况下,正如我在回答中所说,资源字符串的大小对于最终的 exe 大小并不重要(位图和代码更重要)。
    • @A.Bouchez:确实是的,对于直到 D2007 的 delphi 版本,使用 MBCS 代码页时每个字符的字节数不会有差异。
    【解决方案4】:

    使用 resourcestring,编译器将这些字符串作为字符串表资源放置在可执行文件中,允许任何人(比如您的翻译团队)使用资源编辑器编辑它们,而无需重新编译应用程序或访问源代码。

    【讨论】:

      【解决方案5】:

      还有第三种选择:

      常量 MsgErrInvalidInputRange = '这里有无效消息!';

      后者应该是更高性能的,因为告诉编译器不要在数据段中分配空间,它可以将字符串放在代码段中。还要记住,可以用类型常量做什么取决于 $WRITEABLECONST 指令,尽管我不知道编译器究竟什么时候打开或关闭。

      【讨论】:

      • 好一个!我错过了原始帖子中输入的常量。类型化与真实常量的开销是指针取消引用。但是,无论如何,这两个字符串都会进入 .data 部分。将一些数据放入代码段需要asm S db 'foo' 和一些技巧将 OFFSET S 传递到外部范围。 IIRC,可写类型常量和初始化变量是完全等价的。
      • 在代码段中存储数据是可能的,不需要任何技巧,只要段是可读的,而不仅仅是可执行的。我不知道 Delphi 编译器是否仍然这样做,我确信旧的 TP 编译器做到了。此外,AFAIK 也没有记录如何存储和处理真正的常量和类型化的常量。
      • 这不会“更高效”。如果存储在数据或代码部分中,它将被编码完全相同。
      • 缓存性能可能有利于在使用它的代码附近声明的字符串
      猜你喜欢
      • 2011-09-23
      • 2011-07-17
      • 2013-11-25
      • 1970-01-01
      • 2013-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-06
      相关资源
      最近更新 更多