如何正确确定文本文件的字符编码?

 雷宠专业摄影工作室 发布于 2023-02-08 14:21

这是我的情况:我需要正确确定哪个字符编码用于给定的文本文件.希望它能正确返回以下类型之一:

enum CHARACTER_ENCODING
{
    ANSI,
    Unicode,
    Unicode_big_endian,
    UTF8_with_BOM,
    UTF8_without_BOM
};

到目前为止,我可以正确地告诉文本文件Unicode,Unicode big endian或者UTF-8 with BOM通过调用以下函数.它还可以正确地确定ANSI给定的文本文件是否最初不是UTF-8 without BOM.问题是,当文本文件是UTF-8 without BOM,以下函数将错误地将其视为ANSI文件.

CHARACTER_ENCODING get_text_file_encoding(const char *filename)
{
    CHARACTER_ENCODING encoding;

    unsigned char uniTxt[] = {0xFF, 0xFE};// Unicode file header
    unsigned char endianTxt[] = {0xFE, 0xFF};// Unicode big endian file header
    unsigned char utf8Txt[] = {0xEF, 0xBB};// UTF_8 file header

    DWORD dwBytesRead = 0;
    HANDLE hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE)
    {
        hFile = NULL;
        CloseHandle(hFile);
        throw runtime_error("cannot open file");
    }
    BYTE *lpHeader = new BYTE[2];
    ReadFile(hFile, lpHeader, 2, &dwBytesRead, NULL);
    CloseHandle(hFile);

    if (lpHeader[0] == uniTxt[0] && lpHeader[1] == uniTxt[1])// Unicode file
        encoding = CHARACTER_ENCODING::Unicode;
    else if (lpHeader[0] == endianTxt[0] && lpHeader[1] == endianTxt[1])//  Unicode big endian file
        encoding = CHARACTER_ENCODING::Unicode_big_endian;
    else if (lpHeader[0] == utf8Txt[0] && lpHeader[1] == utf8Txt[1])// UTF-8 file
        encoding = CHARACTER_ENCODING::UTF8_with_BOM;
    else
        encoding = CHARACTER_ENCODING::ANSI;   //Ascii

    delete []lpHeader;
    return encoding;
}

这个问题已经阻止了我很长时间,我仍然找不到一个好的解决方案.任何提示将不胜感激.

1 个回答
  • 对于初学者来说,没有像"Unicode"这样的物理编码.您可能的意思是UTF-16.其次,任何文件在"ANSI"中都有效,或者就此而言是任何单字节编码.你唯一能做的就是猜测最有可能抛出无效匹配的最佳顺序.

    您应该按此顺序检查:

    一开始是否有UTF-16 BOM?然后它可能是UTF-16.使用BOM作为指示器,无论是大端还是小端,然后检查文件的其余部分是否符合.

    一开始是否有UTF-8 BOM?然后它可能是UTF-8.检查文件的其余部分.

    如果上述结果不匹配,请检查整个文件是否有效UTF-8.如果是,它可能是UTF-8.

    如果上面没有产生正匹配,那么它可能是ANSI.

    如果你期望没有 BOM的UTF-16文件(例如,可以在XML声明中指定编码的XML文件),那么你也必须在那里推送该规则.虽然上述任何一种都可能产生误报,但错误地将ANSI文件识别为UTF-*(尽管不太可能).您应始终使用元数据来告诉您文件的编码,在无法实现100%准确率的情况下检测文件.

    2023-02-08 14:23 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有