获取错误而读Unicode文件用C
问题描述:
我想用下面的代码来读取C(Cygwin的/ GCC)Unicode文件:获取错误而读Unicode文件用C
#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¼
在阅读它,我总是在 “g_io_channel_read_line” while循环中得到以下错误信息:
0x800474f8“无效的B- yte序列转换输入“
我做错了什么?如何在C中使用glib读取这样的文件?
编辑:进制打印文件的
答
你的文件包含(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二进制
你的文本文件,可以/不可以包括初始BOM(字节顺序标记)。显示文本文件前10个字节左右的十六进制转储。顺便说一句,除了3编码以外,还存在其他编码。 GTG – chux
@chux hexdump添加的文件。 –