Delphi XE2中的AnsiFormat()和ANSI字符串常量

5

有没有一个方便的Format()函数只能用于Ansi字符串?因为每次我使用AnsiString与Format()一起使用时,我都会收到警告。不,我不想让Delphi在宽字符和Ansi字符之间来回转换我的AnsiStrings。那只会使事情变得非常慢。另外,是否有一种方法可以强制一个字符串常量为Ansi?看这个:

function SomeStrFunc(S: AnsiString): AnsiString; overload;
function SomeStrFunc(S: String): String; overload;

当我使用SomeStrFunc('ABC')时,它会调用宽字符串版本。如果我想使用Ansi版本并强制Delphi将'ABC'常量存储在AnsiChars中怎么办。


5
你为什么想要使用 AnsiString?你提到了性能。使用 Unicode 确实会显著降低性能吗?你如何计时的?你是否知道 Ansi Windows API 函数比本地 Unicode 版本慢? - David Heffernan
1
因为 AnsiStrings 占用的空间只有 UnicodeStrings 的一半,如果你正在开发一个专业级别的应用程序,这将非常重要。想象一下一个被全球数百人同时运行的应用程序,通过互联网向日志服务器发送数百条日志消息(仅警告,不包括错误和信息、调试消息)。再想想它是否通过 3G 连接运行。我可以列举出其他数十种情况,在这些情况下,UnicodeStrings 完全无用,而且会浪费时间、空间和金钱。 - Brian Hawk
对于国际化程序而言,ANSI 编码并不是很有用。为了节省空间,可以使用 UTF8 编码。如果受到带宽限制,可以使用压缩技术。 - David Heffernan
2
是的,混合使用Unicode和Ansi确实会变慢。(我不是在谈论仅使用Unicode的原因)。每次在Ansi和Unicode之间进行转换都涉及到内部UStrFromLStr()函数的调用,该函数通过InternalUStrFromPCharLen()进行调用,后者调用WCharFromChar(),后者调用UnicodeFromLocaleChars(),后者调用WinAPI函数MultiByteToWideChar(),在那里你可以说你已经不在堪萨斯了,并告别你珍贵的时钟滴答声。想象一下每秒进行这些转换数百次。所以,是的,它非常慢。 - Brian Hawk
在我看来,如果你考虑到函数每秒被调用超过10次的情况下,压缩不是一个可选项。而且UTF8比普通的Ansi更慢。 - Brian Hawk
1
当你的带宽受限时,压缩会更快。这是通信协议的标准。如果你使用 ANSI,那么只能依赖 ASCII,此时 UTF8 是相同的。如果你对 ASCII 满意,那就好。但如果你需要支持国际观众,那么 ASCII 就变得相当有限了。 - David Heffernan
2个回答

11

System.AnsiStrings单元中有Format函数的Ansi版本。


谢谢,我需要那个。你知道 Delphi XE 的解决方案吗? - Ritsaert Hornstra
@Ritsaert - 是的,AnsiStrings单元存在于所有Unicode Delphi版本中(2009及以上)。 - kludg
谢谢@Serg。System.AnsiStrings单元原来是一个宝藏。 - Brian Hawk

7

Serg已经回答了你有关Format()AnsiString版本的问题。我来回答你的其他问题。

字符串字面量的编码基于它们使用的上下文,所以为了强制一个字面量使用特定的编码方式,你需要告诉编译器需要使用哪种编码方式,例如:

SomeStrFunc(AnsiString('ABC'));

或者

const
  cABC: AnsiString = 'ABC';

SomeStrFunc(cABC);

3
除非将其赋值给不同字符串类型的变量,否则您不需要告诉编译器如何存储文字。如果将相同的文字分别赋值给字符串和 AnsiString 变量,则编译器将在可执行文件中存储两个版本。我很确定这一点(https://dev59.com/SG855IYBdhLWcg3whExL#4293415)。不确定编译器是否对传递文字值到字符串/AnsiString 参数具有相同的行为。 - Marjan Venema
它确实具有相同的行为,@Marjan。在单个程序中,未类型化的字符串常量可以假定许多不同的类型,包括AnsiString、UnicodeString、PChar和Char。 - Rob Kennedy
我其实很害怕不得不使用第二种方法,因为那非常繁琐。而第一种方式绝对不是我想要使用的方式,但仍然可以完成工作。我有点希望能像在C/C++中使数字常量长的方式一样使用'ABC'A,但我想我可以typedef AS = AnsiString;,然后只需使用AS('ABC')。 - Brian Hawk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接