我想使用以下代码在C(Cygwin / GCC)中读取unicode文件:
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
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
答案 0 :(得分:1)
您的文件包含(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”
二进制为空