RawByteString
是一个默认没有设置代码页的AnsiString
。
当你将另一个string
赋值给这个RawByteString
变量时,你会复制源string
的代码页。这将包括一次转换。抱歉。
但是还有另一种使用RawByteString
的方法,就是存储纯字节内容(例如数据库BLOB字段内容,就像一个array of byte
)
总结一下:
RawByteString
应该作为“代码页不可知”的方法或函数的参数;
RawByteString
可以用作存储一些BLOB数据的变量类型。
如果你想减少转换,并且更愿意在你的应用程序中使用8位字符string
,你应该:
- 不要使用通用的
AnsiString
类型,它将依赖于当前系统代码页,并且你将失去数据;
- 依赖于UTF-8编码,即一些8位代码页/字符集,当从或转换为
UnicodeString
时不会丢失任何数据;
- 不要让编译器显示关于隐式转换的警告:所有转换都应该明确指定;
- 使用你自己的专用函数集来处理你的UTF-8内容。
这正是我们为我们的框架所做的。我们想在其内核中使用UTF-8,因为:
- 我们依赖于UTF-8编码的JSON进行数据传输;
- 内存消耗将更小;
- 使用的SQLite3引擎将文本作为UTF-8存储在其数据库文件中;
- 我们希望有一种处理Unicode文本的方式,在所有版本的Delphi(从Delphi 6到XE)中不会丢失数据,并且
WideString
不是一个选项,因为它非常缓慢,并且你会遇到隐式转换的同样问题。
但是,为了实现最佳速度,我们编写了一些优化的函数来处理我们的自定义字符串类型:
{$ifdef UNICODE} RawUTF8 = type AnsiString(CP_UTF8);
{$else} RawUTF8 = type AnsiString; {$endif}
function Trim(const S: RawUTF8): RawUTF8;
function Pos(const substr, str: RawUTF8): Integer; overload; inline;
我们保留了 RawByteString
类型来处理 BLOB 数据:
{$ifndef UNICODE}
RawByteString = AnsiString;
PRawByteString = ^RawByteString;
{$endif}
function FileFromString(const Content: RawByteString; const FileName: TFileName;
FlushOnDisk: boolean=false): boolean;
我们的代码库提供源代码。在这个单元中,为了更快速度,UTF-8相关的函数得到了深度优化,同时提供了pascal和asm版本。我们有时重载默认函数(比如Pos
)以避免转换。关于在框架中处理文本的更多信息,请点此查看。
最后一句话:
如果你确定你的应用程序只包含7位内容(没有重音字符),可以在程序中使用默认的AnsiString
类型。但在这种情况下,最好在uses
子句中添加AnsiStrings
单元,以获得重载的字符串函数,避免大部分不必要的转换。
System.@UStrFromPCharLen
将调用MultiByteToWideChar
将AnsiString
转换为UnicodeString
)。这会使您的代码变慢。甚至在RTL的某些部分中存在一些不必要的转换(请参见IntToStr()在Delphi 2010下至少是非常缓慢的)。 - Arnaud Bouchez