如何以二进制模式读取UTF-8文件并使用C

时间:2017-04-21 17:59:33

标签: c unicode utf-8 utf-16

我是这个Unicode世界的新手,我不知道如何使用C.我不在* nix系统上。我使用的是fedora linux。 我尝试以二进制模式打开UTF-8文件,然后将每个字节读取为一个整数,然后将其转换为相应的Unicode Codepoint。但问题是,如何使用UTF-16格式将这个整数写入文本文件中。

生成的UTF-16输出文件必须与刚读取的UTF-8文件相同,但采用UTF-16格式。任何人都可以帮助我吗?我应该从读取UTF-8文件到整数开始吗?因为我在阅读时遇到了麻烦。 我知道我的代码有点乱,我正努力让它变得更好。 提前谢谢!

2 个答案:

答案 0 :(得分:1)

首先,您必须确保理解字符和代码点之间的区别。关于这个问题,我建议你阅读Joel Spolsky的这篇文章:The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)

然后您可以使用可用的ConvertUTF库here。虽然这个库似乎不再受unicode.org的支持,但仍然是一个警告。

在你的情况下你想要从UTF8转换为UTF16,所以你应该使用函数“ConvertUTF8toUTF16”,它接受UTF8(unsigned char)的输入缓冲区并返回UTF16(unsigned short)的输出缓冲区。

所以问题:您应该将输入的UTF8文件作为unsigned char的缓冲区读取,并将输出UTF16文件作为unsigned short的缓冲区写入。 请注意字节序。

最后一条警告:在Microsoft世界中,“Unicode”和UTF16通常是等同的,但在这种情况下,“Unicode”的定义实际上大部分时间都是UCS-2。

答案 1 :(得分:0)

一种解决方案是使用Unicode库,例如ICU-TC,它将为您完成工作。

为了避免库依赖,并转换自己,你需要读取并从可变长度UTF-8编码转换为32位无符号整数,然后将32位整数转换为UTF-16的16位可变长度编码 - 值。

您需要打开输出文件进行二进制写入,使用:

FILE *outfile = fopen(filename,"wb");

UTF-16可以用小端或大端顺序编写。为了消除歧义,UTF-16有一个特殊的字节排序代码点,你先写(0xFEFF)这两个字节出现在文件中的顺序告诉读者文件写入的字节顺序。(见UTF-16 description on wikipedia)代码:

unsigned short int byte_ordering_sentinel = 0xFEFF;
fwrite(&byte_ordering_sentinel, 2, 1, outfile);

对于每个32位整数,您需要遵循UTF-16规则来生成可变长度的UTF-16值。对于每个16位UTF-16值,您可以执行以下操作:

fwrite(&next_utf16_value, 2, 1, outfile);

注1 :Endianness是CPU和操作系统的产品。英特尔CPU总是小端。 ARM CPU可以做任何一种,并且在Android下是小端。如果要更改输出的字节顺序,则需要在写入之前对每个16位值进行字节交换。一定要将字节交换初始的byte_ordering_sentinel。

在linux上,您可以{bytes}在.whk.h中使用宏。{/ 3>

注意2 :使用fgetc()时,检查EOF值非常重要。如果有人在您的程序运行时更改了文件,那么您的feof(arq)检查和fgetc()调用之间可能存在竞争条件。你的循环可能看起来像这样:

while ( (num=fgetc(arq)) != EOF )