3

我使用德尔福 7。

我需要逐行读取一个 utf-8 文件,每行包含一个单词及其权重(一个数字)所以我需要读取每一行,然后将一行除以分隔符(tab char)并将其保存在内存中.

所以,

1)是否有一个库可以在 Delphi 中处理 utf-8 文件(可能是第 3 方)

2) 函数使用宽字符串可以正常运行吗?我使用 PosEx。那么,如果他们不这样做,您是否还可以提供指向 3-rd 方库的链接以使用宽弦?

4

5 回答 5

4

如果您正在处理的确实是 UTF-8,那么就读取和处理它们而言,您应该不需要任何特殊的东西。您应该能够将它们视为 pchar 甚至是普通的 Delphi 7 字符串。如果您尝试在某种消息框中显示内容,那么您可能需要进行一些转换。例如,如果字符串包含超过 127 (0x7f) 的任何字节值,我不相信 Delphi 7 消息框方法会正确显示 UTF-8 字符串。对于类似的事情,您需要转换为 UTF-16 并调用 Windows API MessageBoxW 或类似的东西。但是,在其他情况下,UTF-8 字符串在许多情况下可以被视为与单字节 ANSI 字符串相同。

我不认为 UTF-8 通常被称为“宽字符串”。我可能错了,但我认为这通常意味着 UTF-16。

于 2011-01-07T21:23:10.360 回答
2

如果您的文件被编码为 UTF-8,并且您要查找的字符是 ASCII,那么根本不需要使用WideString。ASCII 是 UTF-8 的子集,任何 ASCII 字符都保证不会干扰 UTF-8 中用于其他字符的特殊编码。0通过的数字字符9和制表符都是 ASCII。

JCL带有各种处理 Unicode 的函数和类,如果您发现确实需要使用它们。

于 2011-01-07T21:26:38.447 回答
1

如果您的大部分输入是 UTF-8,则可能值得在启动时将代码页从“默认”更改为 utf8(代码页 65001)。这将使所有 ansistring->widestring 转换有效地成为无损 utf-8->utf-16。

使用 D7,您将需要一组所谓的“unicode”组件,这些组件基于 winapi -W 函数。Delphi 自己的组件仅在分水岭 D2009 版本中执行此操作,该版本将默认字符串类型切换为 UTF-16。

如果您想在 Unicode 支持上投入巨资,升级可能是明智之举

于 2011-01-08T00:13:36.083 回答
1

WideString 是一个 UTF-16 实现(与 COM BSTR 兼容),它不能存储 UTF-8 字符串,如果你分配一个 8 位字符串,它将被转换为 UTF-16。但除非您明确使用正确的转换函数,否则 Delphi 将使用当前代码页解释 8 位字符串。

UTF-8 字符串可以存储在 Delphi AnsiString(Delphi 7 中的默认字符串类型)中,但字符串操作函数是为 ANSI 代码页设计的,而不是 UTF-8。不同之处在于 UTF-8 是一个多字节字符集。但是前 127 个 ANSI 字符,编码一个给定的“字符”需要超过一个字节,而许多 ANSI 代码页(尤其是欧洲语言的那些)只需要一个字节,只编码 255 个“字符”(而 UTF-8 可以编码整个 Unicode 集)。

如果您只是在寻找制表符 AFAIK,您可以简单地使用 AnsiString,但您必须确保您可能需要寻找的任何高于 $80 的字节都不是多字节序列的一部分。如果您有更复杂的处理需求,找到处理 UTF-16 字符串的库可能比 UTF-8 更容易。正如 Rob Kennedy 所说,作为实现 UTF 字符串操作的免费库,JCL 是一个很好的起点。

于 2011-01-07T22:02:19.337 回答
0

您可以通过其 LoadFrom...() 方法简单地将文件按原样读取到普通的 TStringList 中,然后根据需要循环遍历列表。如果无法一次将整个文件加载到内存中,则可以使用 TFileStream 打开文件,然后使用 TStreamReader.ReadLine() 方法逐行读取流。

如果您需要将给定的 UTF-8 序列解码为 UTF-16 进行处理,那么我建议直接使用 Win32 API MultiByteToWideChar() 函数,只是因为 RTL 的 UTF8Decode() 函数在旧的 Delphi 中具有损坏的 UTF-8 实现版本(不确定 D7,但它肯定在 D6 中)。

两种加载方法的好处是它们在 D2009 及更高版本中都支持编码,这意味着如果您升级,您可以进行一些非常小的代码更改来告诉 RTL 数据是 UTF-8,它会自动为您将其解码为 UTF-16,然后您的其余处理代码可以保持不变(假设您没有做任何特定于 Ansi 的事情)。

于 2011-01-09T09:17:11.833 回答