使用WideString(utf-8文件)的ReadLn工作原理

3
我使用的是Delphi 7。
我需要逐行读取一个UTF-8文件,每一行包含一个单词和它的权重(一个数字)。所以我需要读取下一行,然后用分隔符(制表符)来分割一行并将其保存在内存中。
因此,
1)是否有一个库可以在Delphi中处理UTF-8文件(第三方库可能会有)?
2)函数是否能够与WideString一起正常工作?我使用PosEx。如果不能,请您提供一个用于处理WideStrings的第三方库链接?
5个回答

4
如果你确实在处理UTF-8,那么在读取和处理时不需要任何特殊操作。你可以将它们视为pchar或者普通的Delphi 7字符串。如果你尝试在某种消息框中显示内容,那么可能需要进行一些转换。例如,如果字符串中包含127(0x7f)以上的字节值,则我认为Delphi 7消息框方法无法正确显示UTF-8字符串。对于这样的情况,你需要转换为UTF-16并调用Windows API MessageBoxW或类似的函数。否则,UTF-8字符串在许多情况下可以像单字节ANSI字符串一样处理。
我认为UTF-8通常不被称为“widestring”。我可能错了,但我认为这通常意味着UTF-16。

2
如果您的文件已经以UTF-8编码,并且您要查找的字符是ASCII字符,那么根本不需要使用WideString。ASCII是UTF-8的子集,任何ASCII字符都保证不会干扰UTF-8中用于其他字符的特殊编码。数字字符09和制表符都是ASCII字符。
如果您发现确实需要使用Unicode,则JCL提供了各种处理Unicode的函数和类。

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所说,JCL是一个很好的起点,作为实现UTF字符串操作的免费库。


1
如果大部分输入都是UTF-8,那么在启动时将代码页从“默认”更改为utf8(代码页65001)可能是值得的。这将使所有ansistring->widestring转换有效地成为无损的utf-8->utf-16。
使用D7,您需要一组所谓的“unicode”组件,这些组件基于winapi-W函数。Delphi自己的组件只有在分水岭D2009发布中将默认字符串类型切换为UTF-16时才会这样做。
如果您想大力投资于Unicode支持,升级可能是一个明智的选择。

0

您可以通过TStringList的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特定操作)。


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