在utf-8中使用ftell和打印问题

时间:2013-10-09 14:36:10

标签: c utf-8

我有两个问题: 1)测试此代码时,显示的buf前面会有一些额外的字符。 (当文件为空时,由于某种原因fsize设置为3。)

2)该文件包含utf-8字符,并且在控制台中无法正确显示,我尝试将语言环境设置为LC_ALL,但似乎没有任何效果。

void display_title(void)
{
    FILE *fh;
    char *buf;
    long fsize;

    fh = fopen("title.txt", "r");
    if (fh == NULL)
    {
        fprintf(stderr, "Unable to open title.txt for read\n");
        return;
    }

    fseek(fh, 0L, SEEK_END);
    fsize = ftell(fh);
    rewind(fh);
    buf = malloc(sizeof(char)*fsize);

    fread(buf, fsize, 1, fh);
    fclose(fh);

    fwrite(buf, fsize, 1, stdout);
    free(buf);
}

编辑:所以我写了一个函数来检查文件的编码,但有些事情仍然关闭。我检查了文件,我知道它是UTF_8,但它没有在我的函数中注册。我觉得某处有一个错误,但我没有看到它。

// Check for BOM in file
// ERROR : file too small
// NONE : does not exist
// UTF_8_ENCODING : for utf_8 enoding found
// UTF_16_ENCODING : for utf_16 encoding found
// UTF_32_ENCODING : for utf_32 encoding found
int check_encoding(int fd)
{
    char *buf;
    off_t fsize;

    fsize = lseek(fd, 0L, SEEK_END);

    if (fsize < 2)
        return ERROR;

    buf = (char*)malloc(2 * sizeof(char));
    lseek(fd, 0L, SEEK_SET);
    read(fd, buf, 2);

    if (!strncmp(buf, UTF_16_BE, 2) ||
        !strncmp(buf, UTF_16_LE, 2))
    {
        free(buf);
        return UTF_16_ENCODING;
    }

    if (fsize >= 3)
    {
        realloc(buf, 3);

        if (!strncmp(buf, UTF_8, 3))
        {
            free(buf);
            return UTF_8_ENCODING;
        }
    }

    if (fsize >= 4)
     {
        realloc(buf, 4);

        if (!strncmp(buf, UTF_32_BE, 4) ||
            !strncmp(buf, UTF_32_LE, 4))
        {
            free(buf);
            return UTF_32_ENCODING;
        }
    }

    free(buf);
    return FALSE;
}

1 个答案:

答案 0 :(得分:1)

很难说为什么UTF-8没有在你的控制台上正确显示,但我认为开头有三个额外字节有一个简单的原因:很可能你的文件以Byte order mark (BOM)开头

修改: 对于UTF-8编码文件,BOM(如果存在)将始终为字节序列0xEF,0xBB,0xBF。因此,如果想要处理可能包含或不包含BOM的文件,可以只读取前三个字节,检查它们是否为该值,如果它们是BOM,则忽略它们。

如果您不知道文件的编码(UTF-8,UTF-16,...),则可以使用BOM来确定它。我链接的维基百科文章显示了它在不同编码中的表示方式。