在 Delphi 2007 及更早版本中处理 Unicode 字符串

12

背景: 这个问题涉及 Delphi 2009 以下的版本(即没有内置 Unicode 支持)。我有一个需要我通过 TCP 连接传输 Unicode 编码字符串的规范,但我没有 Delphi 2009。

问题: 是否有一个单一的函数或非常小的库(我不需要太多的体积),可以在发送到网络之前将单个字符串编码为 UTF-8?作为我的问题的第二部分:如果作为响应发送回来的是 UTF-8 编码的字符串,那么我是否需要另一个函数将其转换回 Delphi 字符串格式。我理解这种方式中 Unicode 支持的限制。


system.pas 文件中的 Utf8ToAnsi 和 AnsiToUtf8 怎么样? - Uwe Raabe
5个回答

29

Delphi 2009之前的版本已经有内置Unicode支持了。自Delphi 4以来就一直提供了WideString类型,甚至更早。虽然WideString不如新的UnicodeString类型简洁,但它仍然包含16位的Unicode字符,并且你可以将其类型转换为PWideChar,以便将字符串发送到Unicode API函数。 Windows单元声明了大多数"wide"版本的API函数,如果您发现缺少某些函数,您也可以自行声明其他函数。

之前的版本没有的是VCL中的Unicode支持。此时,您可以使用Tnt Unicode控件。它们曾经是免费的。看起来还有几个地方可以找到最新的免费版本:(1)(2)

JCL有几个用于处理Unicode的单元。 JclWideStrings单元主要包含轻量级的实用程序函数。 JclUnicode单元更全面,但也包括一个庞大的资源,用于确定所有Unicode字符的字符属性。

使用JCL,您有几种选择用于保存WideString值列表的类。我认为Delphi 7甚至都有一个用于此目的的类。

不要认为仅因为您没有Delphi 2009就不能编写Unicode程序。

如果您有一个WideString值,并且想将其编码为UTF-8,则需要调用Utf8Encode函数。它将返回一个AnsiString值,或者如果您的Delphi版本声明了该类型,则可能返回Utf8String。但这与Delphi 2009的Utf8String类型不同。在赋值语句中,Delphi 2009会自动转换为UnicodeStringAnsiString(x),反之亦然。而之前的版本只有一个AnsiString类型,因此您需要自己跟踪哪些变量保存UTF-8数据,哪些保存Ansi数据(在变量和参数名上使用匈牙利命名法可以帮助您进行跟踪)。当然,还有一个Utf8Decode函数,用于将UTF-8数据转换回WideString
对于处理其他字符编码,您可以查看Delphi的免费XML库Open XML。作为其XML处理的一部分,它支持在70种不同编码之间转换。

3
在 Delphi 2009 之前,如果您将一个 WideString 赋值给一个 String,会自动将 Unicode 转换为字符串 AnsiString,并使用进程的当前代码页。如果您想要使用 UTF-8 而不是当前的代码页进行字符存储,则需要使用 Utf8Decode/Utf8Encode。 - Arnaud Bouchez
那个指向JCL的链接似乎已经过时了。http://wiki.delphi-jedi.org/index.php?title=JEDI_Code_Library 是当前的等效链接吗? - Jessica Brown

6

使用WideString类型和对应的编码函数进行UTF8的转换(UTF8Encode/UTF8Decode)。

不要使用string类型和Ansi函数进行转换,如果这样做,您将丢失信息。


如果 OP 确实意识到 Unicode 支持的限制,并且所有涉及的 UTF-8 编码字符串可以在当前系统字符集中进行转换,而不会丢失任何信息,那么这个答案是错误的。 - mghie

6

我在Delphi 2009发布之前,构建了一个完整的Unicode应用程序。

我使用了以下内容:

  1. 将widestring用作主要的字符串数据类型。

  2. 使用支持Unicode的数据库组件(ADO也使用widestring,但我没有使用它,因为它不能处理Unicode字段名称)。

  3. 使用免费的TNTControls进行UI设计,效果很好,但与标准控件相同,没有其他第三方控件那么多功能。

  4. 我设置了一个虚拟机,安装了不同的语言,以便可以在不支持我的语言的系统中测试该版本。

  5. 我的报表工具是支持Unicode的FastReport。

此外,我还使用了DIConverters来转换数据库从ansi到UTF8,并使用其函数进行转换,它是免费软件;-)

还有一个开源项目Delphi fundamentals,它具有对Unicode非常有用的功能。

但我认为,如果您能使用D2009来完全支持Unicode,那么您的工作将会更加容易和快速,因为您不会使用缓慢的widestring数据类型,并且您会发现大多数第三方提供了Unicode版本或正在开发中。


5
将一个Delphi 2009之前的应用程序转换为Unicode是困难的,但是可以实现。我建议将其分为3个任务。
  1. 首先,请确保您的数据库处理Unicode字符串。最好支持UTF-16。确保所有数据库代码正确处理widestring,并且您使用的驱动程序也可以处理它。
  2. 将所有业务逻辑从使用字符串转换为使用WideStrings。很容易错过一些部分,并且如果您忘记任何方法,编译器将会隐式地将widestring转换为字符串而不会报错。还要确保将所有标准字符串函数更改为WideString等效函数。此过程需要扩展到您可能使用的任何第三方组件。
  3. 最后一步是将您可能拥有的标准和第三方可视组件更改为WideString等效组件。这需要在您将显示可能包含Unicode字符的字符串的任何位置进行。

除此之外,确保您的测试充分,并使用实际使用高字节的Unicode字符。如果您只使用拉丁字符集进行测试,则会错过错误。


为什么数据库需要支持UTF-16?对于使用系统转换函数进行Ansi <-> UTF-8的Ansi Delphi程序来说,UTF-8可能更适合。 - mghie
使用WideString(非引用计数,COM重型)处理UTF-16。 使用TUtf8String / string(引用计数,轻量级)处理UTF-8,确保执行类似“type TUtf8String = type string;”这样的操作,以使TUtf8String与string区别但兼容。 - Jeroen Wiert Pluimers

3
如果你只需要将程序内部的字符串从系统编码转换为UTF-8并进行相反的操作,那么请使用Uwe Raabe提到的库函数。如果你仍然在使用Delphi 4或5(这些版本没有这些函数),则可以使用GNU gettext for Delphi中的函数。
不要被所有关于完全使用WideString的答案吓到 - 在普通的Ansi Delphi程序中使用UTF-8作为数据交换的编码方式(这是我理解你问题的方式)应该是可能的,只要你处理的数据在你的Windows编码中是100%可表示的即可。

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