在C中读取unicode文件时出错

我想使用以下代码在C(Cygwin / GCC)中读取unicode文件:

#include  #include  #include  void split_parse(char* text){ char** res = g_strsplit(text, "=", 2); printf("Key = %s : ", res[0]); printf("Value = %s", res[1]); printf("\n"); } int main(int argc, char **argv) { setenv ("CYGWIN", "nodosfilewarning", 1); GIOChannel *channel; GError *err = NULL; int reading = 0; const gchar* enc; guchar magic[2] = { 0 }; gsize bytes_read = 0; const char* filename = "C:\\CONFIG"; channel = g_io_channel_new_file (filename, "r", &err); if (!channel) { g_print("%s", err->message); return 1; } if (g_io_channel_set_encoding(channel, NULL, &err) != G_IO_STATUS_NORMAL) { g_print("g_io_channel_set_encoding: %s\n", err->message); return 1; } if (g_io_channel_read_chars(channel, (gchar*) magic, 2, &bytes_read, &err) != G_IO_STATUS_NORMAL) { g_print("g_io_channel_read_chars: %s\n", err->message); return 1; } if (magic[0] == 0xFF && magic[1] == 0xFE) { enc = "UTF-16LE"; } else if (magic[0] == 0xFE && magic[1] == 0xFF) { enc = "UTF-16BE"; } else { enc = "UTF-8"; if (g_io_channel_seek_position(channel, 0, G_SEEK_CUR, &err) == G_IO_STATUS_ERROR) { g_print("g_io_channel_seek: failed\n"); return 1; } } if (g_io_channel_set_encoding (channel, enc, &err) != G_IO_STATUS_NORMAL) { g_print("%s", err->message); return 1; } reading = 1; GIOStatus status; char* str = NULL; size_t len; while(reading){ status = g_io_channel_read_line(channel, &str, &len, NULL, &err); switch(status){ case G_IO_STATUS_EOF: reading = 0; break; case G_IO_STATUS_NORMAL: if(len == 0) continue; split_parse(str); break; case G_IO_STATUS_AGAIN: continue; case G_IO_STATUS_ERROR: default: //throw error; reading = 0; break; } } g_free(str); g_io_channel_unref(channel); return(EXIT_SUCCESS); } 

文件(C:\ CONFIG)内容如下:

 h-debug="1" name=ME ÃÆÿЮ©=2¾1¼ 

在阅读它时,我总是在while循环中的“g_io_channel_read_line”处收到以下错误消息:

0x800474f8“转换输入中的字节序列无效”

我究竟做错了什么? 如何使用glib在C中读取这样的文件?

编辑:文件的Hexdump

在此处输入图像描述

您的文件包含(EF BB BF)的3字节UTF8 BOM。 字节顺序标记。

您的代码默认为UTF8,但不使用BOM。

 channel, 0, G_SEEK_CUR, &err 

S / B

 channel, 3, G_SEEK_CUR, &err 

此外,我建议扩展您的magic代码以读取4个字节并肯定地辨别BOM。

如果您没有找到BOM,您可以假设我认为是二进制的编码NULL。 或抛出错误或修复任性的文本文件或者,如果您是迂腐的,请按顺序尝试所有已知的编码类型。


UTF32BE“\ x00 \ x00 \ xFE \ xFF”
UTF32LE“\ xFF \ xFE \ x00 \ x00”
UTF8“\ xEF \ xBB \ xBF”
UTF16BE“\ xFE \ xFF”
UTF16LE“\ xFF \ xFE”
二进制为NULL