【发布时间】:2014-01-11 20:42:25
【问题描述】:
这是我的情况:我需要正确确定给定文本文件使用哪种字符编码。希望它可以正确返回以下类型之一:
enum CHARACTER_ENCODING
{
ANSI,
Unicode,
Unicode_big_endian,
UTF8_with_BOM,
UTF8_without_BOM
};
到目前为止,我可以通过调用以下函数正确判断文本文件是Unicode、Unicode big endian 或UTF-8 with BOM。如果给定的文本文件最初不是UTF-8 without BOM,它还可以正确确定ANSI。 问题是当文本文件为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;
}
这个问题困扰了我很长时间,我仍然找不到好的解决方案。任何提示将不胜感激。
【问题讨论】:
-
术语“ANSI”经常被错误地用来指代 8 位编码,通常是 Windows 特定的编码之一,例如 Windows-1252,它从未成为 ANSI 标准。在微软的世界里,“Unicode”这个词经常被错误地用来指代 UTF-16 编码。 Unicode 不是一种编码,但是有几种编码可以用来表示 Unicode。 ASCII 文件与 UTF-8 文件无法区分,而 UTF-8 文件恰好包含 0..127 范围之外的任何字符。大多数 UTF-8 文件不以 BOM 开头(因为 UTF-8 没有字节顺序)。
-
不要在注释中枚举编码类型,而是在
enum中枚举它们。
标签: c++ text character-encoding