Delphi XE - RawByteString 与 AnsiString

2023-11-23

我在这里有一个类似的问题:Delphi XE - 我应该使用 String 还是 AnsiString?。在决定在我的(大型)库中使用 ANSI 字符串是正确的之后,我意识到我实际上可以使用 RawByteString 而不是 ANSI。因为我将 UNICODE 字符串与 ANSI 字符串混合在一起,所以我的代码现在很少有地方可以在它们之间进行转换。然而,看起来如果我使用 RawByteString 我就可以摆脱这些转换。

请让我知道您对此的看法。
Thanks.


Update:
这似乎令人失望。看起来编译器仍然进行从 RawByteString 到字符串的转换。

procedure TForm1.FormCreate(Sender: TObject);
var x1, x2: RawByteString;
    s: string;
begin
  x1:= 'a';
  x2:= 'b';
  x1:= x1+ x2;
  s:= x1;              {      <------- Implicit string cast from 'RawByteString' to 'string'     }
end;

我认为它做了一些内部工作(例如复制数据),并且我的代码不会快得多,而且我仍然需要在代码中添加大量类型转换以使编译器保持沉默。


RawByteString is an AnsiString默认情况下没有设置代码页。

当您分配另一个string对此RawByteString变量,您将复制源代码页string。这将包括转换。对不起。

但还有另一种用途RawByteString,用于存储纯字节内容(例如数据库 BLOB 字段内容,就像array of byte)

总结一下:

  • RawByteString应该用作方法或函数的“代码页不可知”参数;
  • RawByteString可以作为变量类型来存储一些BLOB数据。

如果你想减少转换,宁愿使用8位字符string在您的应用程序中,您应该更好:

  • 不要使用通用的AnsiString类型,这取决于当前的系统代码页,并且您将丢失数据;
  • 依赖 UTF-8 编码,即一些 8 位代码页/字符集,在从 UTF-8 编码或转换为 UTF-8 编码时不会丢失任何数据UnicodeString;
  • 不要让编译器显示warnings关于隐式转换:所有转换都应显式进行;
  • 使用您自己的专用函数集来处理 UTF-8 内容。

这正是我们为框架所做的。我们希望在其内核中使用 UTF-8,因为:

  • 我们依靠UTF-8编码的JSON进行数据传输;
  • 内存消耗会更小;
  • 使用过的SQLite3引擎会将文本以 UTF-8 形式存储在其数据库文件中;
  • 我们想要一种处理 Unicode 文本的方法,并且所有版本的 Delphi(从 Delphi 6 到 XE)都不会丢失数据,并且WideString不是一个选择,因为它非常慢并且您遇到了相同的隐式转换问题。

但是,为了实现最佳速度,我们编写了一些优化函数来处理自定义字符串类型:

  {{ RawUTF8 is an UTF-8 String stored in an AnsiString
    - use this type instead of System.UTF8String, which behavior changed
     between Delphi 2009 compiler and previous versions: our implementation
     is consistent and compatible with all versions of Delphi compiler
    - mimic Delphi 2009 UTF8String, without the charset conversion overhead
    - all conversion to/from AnsiString or RawUnicode must be explicit }
{$ifdef UNICODE} RawUTF8 = type AnsiString(CP_UTF8); // Codepage for an UTF8string
{$else}          RawUTF8 = type AnsiString; {$endif}

/// our fast RawUTF8 version of Trim(), for Unicode only compiler
// - this Trim() is seldom used, but this RawUTF8 specific version is needed
// by Delphi 2009/2010/XE, to avoid two unnecessary conversions into UnicodeString
function Trim(const S: RawUTF8): RawUTF8;

/// our fast RawUTF8 version of Pos(), for Unicode only compiler
// - this Pos() is seldom used, but this RawUTF8 specific version is needed
// by Delphi 2009/2010/XE, to avoid two unnecessary conversions into UnicodeString
function Pos(const substr, str: RawUTF8): Integer; overload; inline;

我们保留了RawByteString处理 BLOB 数据的类型:

{$ifndef UNICODE}
  /// define RawByteString, as it does exist in Delphi 2009/2010/XE
  // - to be used for byte storage into an AnsiString
  // - use this type if you don't want the Delphi compiler not to do any
  // code page conversions when you assign a typed AnsiString to a RawByteString,
  // i.e. a RawUTF8 or a WinAnsiString
  RawByteString = AnsiString;
  /// pointer to a RawByteString
  PRawByteString = ^RawByteString;
{$endif}

/// create a File from a string content
// - uses RawByteString for byte storage, thatever the codepage is
function FileFromString(const Content: RawByteString; const FileName: TFileName;
  FlushOnDisk: boolean=false): boolean;

源代码可用在我们的存储库中。在本单元中,对UTF-8相关功能进行了深度优化,同时提供了pascal和asm版本,以获得更好的速度。我们有时会重载默认函数(例如Pos)以避免转换,或者有关我们如何在框架中处理文本的更多信息是可以在这里找到.

遗言:

如果你是sure您的应用程序中只有 7 位内容(无重音字符),您可以使用默认值AnsiString输入你的程序。但在这种情况下,您最好添加AnsiStrings单位在你的uses子句具有重载的字符串函数,这将避免大多数不需要的转换。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Delphi XE - RawByteString 与 AnsiString 的相关文章

  • 对于大型简单数据库,SQLite 和 DISQLite 有何比较?

    两者有什么区别SQLite http www sqlite org and DISQLite http www yunqa de delphi doku php products sqlite3 index为什么我要选择其中一个而不是另一个
  • Unicode、正则表达式和 PyPy

    我写了一个程序来添加 有限 统一码支持 https stackoverflow com q 1832893 520779到 Python 正则表达式 虽然它在 CPython 2 5 2 上工作正常 但在 PyPy 上不起作用 1 5 0
  • FireDac 添加下划线 1 以区分具有相同名称的 2 个列名

    我有一个连接 2 个表的选择 因此这些表中存在具有相似名称的列 因此现在在检索结果时 FireDac 将下划线 1 添加到第二个列名称以区分这两个表 Select from Table1 inner join Table2 on Table
  • Delphi 2005 Web 服务问题

    我在尝试通过 Delphi 访问 Web 服务时遇到问题 我使用了 2007 版 WSDLimp 工具的 java WSDL 看起来它已正确创建了所有对象 然而 当我制作一个调用该服务的测试程序时 每个对象都是空的 如果我在 HTTPRIO
  • 控制台应用程序中使用 Unicode 字符的 _tprintf

    我正在从 Unicode 构建的控制台应用程序 使用 C 和 Visual Studio 2008 执行这个简单的输出 此代码旨在在 Windows 上运行 tprintf L Some sample string n 一切正常 但是如果我
  • Android中如何检测程序的终止?

    当 Windows 程序终止时 它会调用事件处理程序 例如 OnClose OnDestroy 和析构函数 Destroy 当我想保存一些 INI 设置时 这些地方就是我要保存的地方 我为所有这些事件编写了事件处理程序 但当我终止程序时它们
  • 如何在 Linux 中重新添加 unicode 字节顺序标记?

    我有一个相当大的 SQL 文件 它以 FFFE 的字节顺序标记开头 我使用 unicode 感知的 linux 分割工具将此文件分割成 100 000 行块 但是当将这些传递回窗口时 它确实not与第一个部分以外的任何部分一样 只是它具有
  • 为什么 MySQL 将 é 与 e 视为相同?

    我使用 Django Web 应用程序将 Unicode 字符串存储在 MySQL 数据库中 我可以很好地存储 Unicode 数据 但是在查询时 我发现 and e被视为好像它们是同一个角色 In 1 User objects filte
  • Delphi 是否在构造对象之前分配变量?

    Delphi 是否在对象完全构造之前分配实例变量 换句话说 给定一个变量 var customer TCustomer nil 然后我们构造一个客户并将其分配给变量 customer TCustomer Create 有没有可能custom
  • 用 unicode 字符删除纯文本?

    是否可以删除代码注释中不需要的修改过的单词 由于开发人员仍然在黑暗时代更简单的纯文本时代进行编码 其中文本无法使用隐藏标识符进行格式化 因此实现这一目标的唯一方法是使用 Unicode 字符 由于某些unicode字符可以扩展 y o n
  • Firebird 或 NexusDB

    我知道有很多与 Delphi 数据库相关的问题 但我只考虑这两个数据库 我需要查询大约 100 000 条记录 根据您的经验 哪个更快 作为嵌入式 as C S Thanks 我还没用过 Nexus tbh 但我经常使用 Firebird
  • 什么是代码页 0?

    我正在使用Delphi函数 StringCodePage 我在 COM 函数 Acrobat Annotation getContents 请参阅我的其他帖子 返回的字符串上调用它 它返回 0 0是什么 安西 代码页 0 是 CP ACP
  • 如何使用 IdTCPClient 等待来自服务器的字符串?

    我的 IdTelnet indy 10 1 有问题 我无法以 Unicode 模式从服务器读取数据 现在我想用 IdTCPClient 编写 telnet 终端 服务器有时发送一行 有时发送越来越多的行 但发送之间没有固定的时间 现在我的问
  • 是否可以在虚拟树视图中选择多个列?

    我需要添加功能来复制节点和列的矩形选择 但我找不到任何方法来实际选择虚拟树视图中的多个列 除了 toFullRowSelect 之外 我只是错过了什么吗 如果没有 是否有一个后代具有类似网格的多列选择支持 经过一些测试后 我得出了以下结论
  • 使用 python3 查找表情符号的宽度

    我尝试使用 python 中的模式打印字母 A def printA length height symbol a for i in range length for i in range height for i in range hei
  • SQLite 的不区分大小写的 UTF-8 字符串排序规则 (C/C++)

    我正在寻找一种方法 以不区分大小写的方式对 C 中的 UTF 8 字符串进行比较和排序 以便在SQLite 中的自定义排序规则函数 http www sqlite org c3ref create collation html 该方法应该i
  • Delphi:如何计算大文件的 SHA 哈希值

    您好 我需要生成 5 Gig 文件的 SHA 您知道有一个非基于字符串的 Delphi 库可以做到这一点吗 你应该使用DCPcrypt v2 http www cityinthesky co uk cryptography html读取缓冲
  • TCHAR 仍然相关吗?

    我是 Windows 编程新手 在读完 Petzold 的书后 我想知道 使用TCHAR类型和 T 函数来声明字符串或者我应该使用wchar t and L 新代码中的字符串 我将仅针对现代 Windows 截至撰写本文时版本 10 和 1
  • 如何为每个线程自动全局初始化/取消初始化某些内容?

    我有一个单位initialization and finalization部分 该单元包含一个复杂的对象 该对象在initialization并毁于finalization 但是 该对象还包含一个 ADO 连接 这使得跨线程使用它时出现问题
  • PHP UTF-8 问题 - 如果我在 PHP 中创建一个字符串...它是 UTF-8 格式吗?

    在 PHP 中 如果我创建一个像这样的字符串 str bla bla here is my string 然后我可以使用 mbstring 函数将该字符串作为 UTF8 进行操作吗 Will this work str mb strlen

随机推荐

  • 使用 Delphi 6 处理 Unicode 字符

    我有一个用 Delphi 6 开发的轮询应用程序 它读取文件 根据规范解析文件 执行验证并上传到数据库 SQL Server 2008 精简版 我们必须为具有双字节字符集 DBCS 的操作系统提供支持 例如日本操作系统 因此 我们将 SQL
  • 使用 Boost::Regex 获取最后一场比赛

    我在 C 中有一个带有 Boost 的正则表达式 它匹配多行字符串中的行 正则表达式搜索找到第一个匹配项 但是我对匹配的最后一行感兴趣 我现在使用的代码是这样的 matched boost regex search input result
  • 静态锁可以跨不同的子类工作吗?

    如果我有 abstract class Parent static object staticLock new object public void Method1 lock staticLock Method2 protected abs
  • 如何将gradle添加到子项目根项目作为依赖项?

    我有以下项目结构settings gradle include B include C rootProject name A 如何将gradle添加到子项目根项目作为依赖项 就project就方法而言 根项目没有名称 这是项目 B 的 bu
  • 计算总和为零的所有连续子数组

    给定长度为 n 的随机数 正数和负数 数组 我想要数字连续的子数组 其总和等于零 Example 鉴于我有数组a 1 1 2 2 6 6 输出将是6因为子数组如下 1 1 2 2 6 6 1 1 2 2 2 2 6 6 1 1 2 2 6
  • 使用 JPA 注释映射 java.util.Map 时键和值列名称会覆盖

    我正在研究使用 Hibernate 4 1 9 和 JPA 注释来注释地图的不同方法 如果我想存储一个 Map 其中键是实体值的属性 则标记如下所示 OneToMany mappedBy deptById targetEntity com
  • C# 属性集合[重复]

    这个问题在这里已经有答案了 我有一个特定的内置属性集合 例如 System Runtime Serialization SerializedAttribute 我想将其应用于特定的类集合 是否有可能将这些属性合而为一 我不想将它们全部显式应
  • 在一张图上绘制两张图。功能线不起作用

    我想在一张图上绘制两张图 我读这个帖子 但函数lines不起作用 什么也没有发生 我不知道会出现什么问题 有任何想法吗 编辑 可重现的例子 gt tr error 1 0 2314984 0 2314990 0 2314981 0 2314
  • MIME 类型('text/html')不是受支持的样式表

    我正在将 css 文件链接到我的express handlebars 文件 但收到此错误 拒绝应用来自 的样式http localhost 4000 cs366 style draft css 因为它的 MIME 类型 text html
  • 退出当前浏览器(返回一级)

    有时你会抛出多个browser进入一个函数进行调试 我知道你可以退出整个shebangQ但是如果您想退出第二个浏览器 参见下面的代码 并返回到第一级浏览器怎么办 我听说过类型c但这并没有退出第二层browser FUN lt functio
  • 将变量从一个 HTML 页面传递到另一个 HTML 页面的最佳实践是什么?

    我对网络应用程序编程比较陌生 所以我希望这个问题对每个人来说都不是太基础 我创建了一个 HTML 页面 其中包含一个包含 dojox 数据网格 v1 2 的 FORM 其中填充了不同杂货项目的描述行 用户选择他感兴趣的项目后 他将单击 提交
  • UIImagePickerController 的cameraViewTransform 忽略了 iOS 10 beta 上的“缩放”和“平移”

    我一直在使用下面的代码来缩放 UIImagePickerController 的实时预览以填充整个屏幕 到目前为止 这一切都很完美 几天前 我在 iPhone 5 上安装了 iOS 10 beta 7 但它不再扩展了 我可以在 UIImag
  • PCL .NET 4.5 定时器

    我正在使用 Xamarin 和 MvvmCross 构建跨平台应用程序 我需要每分钟调用服务器更新一次 稍后我将转向推送通知 但我无法在我的核心项目中设置计时器 我见过 MvvmCross N 42 但我相信目标项目比较旧 允许计时器 下面
  • Translation.E004) 您为 LANGUAGE_CODE 设置提供了一个不在 LANGUAGES 设置中的值

    我刚刚重新映像了我的计算机 因此为我的 django 项目设置了所有内容 然后在运行服务器时出现此错误 我不知道它指的是什么 因为我的原始网站是开箱即用的 而且我会说英语 并且该网站是一个内部工作网站 因此没有理由做任何基于语言的事情 有谁
  • Angular 2 中的错误处理程序和拦截器有什么区别?

    另外 对于实时 Web 应用程序 ng2 中前端错误处理的最佳解决方案是什么 使用 Http拦截器 进行前端错误处理可以吗 请解释一下这些事情 Angular 2 中的错误处理程序和拦截器有什么区别 根据 Angular 文档 它们是这样定
  • 在 Ubuntu 上更新 TimescaleDB 后 Postgres 出现错误:找不到文件

    如指定官方文档我将 Timescale PPA 存储库添加到apt 然后我通过安装它sudo apt install timescaledb postgresql 9 6 一切都工作正常 随着最近的运行sudo apt upgrade时间刻
  • 更改当前正在运行的进程的所有者

    我有一个当前正在运行的进程pid PID 并由user foo这是not root 我想将此进程的所有权转移给另一个进程user bar这也是not root 是否有一个 shell 命令可以更改进程的所有者 我正在考虑一个chown但对于
  • Stripe:为订阅添加免费天数

    是否可以为 Stripe 上的有效订阅添加免费天数 我想这样做是为了创建一个推荐计划 当用户推荐某人时 他将获得 10 天的免费时间 我认为一个好方法是更新current period endvar 但我在文档中找不到如何执行此操作 例如
  • Array.Sum() 导致溢出

    我有一个像这样的 int 数组 int arr 256741038 623958417 467905213 714532089 938071625 然后我创建了一个 int64 var Int64 sum arr Sum 但这导致了溢出 运
  • Delphi XE - RawByteString 与 AnsiString

    我在这里有一个类似的问题 Delphi XE 我应该使用 String 还是 AnsiString 在决定在我的 大型 库中使用 ANSI 字符串是正确的之后 我意识到我实际上可以使用 RawByteString 而不是 ANSI 因为我将