【问题标题】:ReadLn working with WideString (utf-8 files)ReadLn 使用 WideString(utf-8 文件)
【发布时间】:2011-06-05 13:09:26
【问题描述】:

我用的是delphi 7。

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

所以,

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

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

【问题讨论】:

    标签: delphi utf-8 delphi-7 widestring


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

      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 是一个很好的起点。

      【讨论】:

        【解决方案3】:

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

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

        如果您想大力投资于 Unicode 支持,升级可能是明智之举

        【讨论】:

          【解决方案4】:

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

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

          【讨论】:

            【解决方案5】:

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

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-04-20
              • 1970-01-01
              • 2013-09-14
              相关资源
              最近更新 更多