获取错误而读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读取这样的文件?

编辑:进制打印文件的

enter image description here

+0

你的文本文件,可以/不可以包括初始BOM(字节顺序标记)。显示文本文件前10个字节左右的十六进制转储。顺便说一句,除了3编码以外,还存在其他编码。 GTG – chux

+0

@chux 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二进制