如何检测一个文本文件的编码方式,是否是utf-8无BOM的?

陈晓猫 2019-08-22 02:27:49
看了个帖子。
如何检测一个文本文件的编码方式,策略是什么?
作者给出的有一段代码:
https://www.cnblogs.com/lkpp/p/encoding_detection.html
1、如果2个字节是0xFF 0xFE,则以Unicode(LE)的方式读取,
2、如果2个字节是0xFE 0xFF,则以Unicode BE的方式读取
3、如果前2个字节是0xEF 0xBB,那么判断第3个字节是不是0xBF,如果是的话就以UTF-8的方式进行读取。
4、判断是否符合UTF-8的编码规范,如果符合就以UTF-8的方式进行读取
5、如果以上都不是,则以ANSI的方式进行读取。


关于第4点,具体是怎么实现的,楼上的代码看不懂具体怎么用,可由大神愿意指点一二的?谢谢了!
...全文
1720 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
轻箬笠 2019-08-29
  • 打赏
  • 举报
回复
轻箬笠 2019-08-29
  • 打赏
  • 举报
回复
楼主首先得以二进制的形式打开文件。
类似这样
FILE *fphzk
fphzk=fopen("c:\\hzk16","rb");
然后读取一定的长度。
类似这样
char buf[20];
fread(buf,1,sizeof(buf),fphzk);
之后才是调用
DetectEncode(buf, sizeof(buf));
最后是这样
fclose(fphzk)
schlafenhamster 2019-08-29
  • 打赏
  • 举报
回复
调用

void CMainFrame::OnButton32776()
{
// TODO: Add your command handler code here
char ascii[]="abcdefg";
BOOL ret=CheckNoBOM_utf8((BYTE *)ascii, 7);
afxDump << ret << "\n";// all ascii not utf8
//
char str[]="A丁一万";// ansi
char str8[20]={0};
int len=9;//
WCHAR wBuf[20]={0};
MultiByteToWideChar(CP_ACP,0,str,len,wBuf,len);// ansi 2 unicode
WideCharToMultiByte(CP_UTF8,0,wBuf,len,str8,len,0,0);// unicode to utf8
//str8="A\xE4\xB8\x81\xE4\xB8\x80\xE4\xB8\x87";
len=strlen(str8);
ret= CheckNoBOM_utf8((BYTE *)str8,len);
afxDump << ret << "\n";
}
陈晓猫 2019-08-29
  • 打赏
  • 举报
回复
schlafenhamster,谢谢您的回复,直接上代码。算法我大概了解,一楼我提问的时候已经有相应的算法了,我不懂的是如何pBuffer怎么定义,怎么用,length又是什么,pText又怎么赋值。

轻箬笠,感谢您的回复!明白了。我不是用的您给出的代码,用的windows api来复制文件到内存。问题已解决。
schlafenhamster 2019-08-28
  • 打赏
  • 举报
回复

/* 无 BOM 检测 UTF-8
UCS-4 range (hex.) UTF-8 octet sequence (binary)
0000 0000-0000 007F 0xxxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx // 110 表示 2个字节,一个UTF-8
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx // 1110 表示3个字节,一个UTF-8
0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx // 11110 表示4个,字节一个 UTF-8
0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx // 111110 表示5个字节,一个 UTF-8
0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx // 1111110 表示 6个字节 ,一个 UTF-8
*/
BOOL CheckNoBOM_utf8(BYTE *pText, long length)
{
int i;
DWORD nBytes = 0;
UCHAR chr;
BOOL bAllAscii = TRUE;
// all chars
for (i = 0; i < length; i++)
{
chr = *(pText + i);
if ((chr & 0x80) != 0) bAllAscii = FALSE;// 0xxxxxxx
if (nBytes == 0)
{// check 1st
if (chr >= 0x80)
{
if (chr >= 0xFC && chr <= 0xFD) nBytes = 6;
else if (chr >= 0xF8) nBytes = 5;
else if (chr >= 0xF0) nBytes = 4;
else if (chr >= 0xE0) nBytes = 3;
else if (chr >= 0xC0) nBytes = 2;
else return FALSE;
nBytes--;
}
}
else
{// 10xxxxxx
if ((chr & 0xC0) != 0x80) return FALSE;// not 10xxxxxx
nBytes--;// next "10xxxxxx"
}
}
// more "10xxxxxx" than nBytes
if (nBytes > 0) return FALSE;
// all bytes is ascii
if (bAllAscii) return FALSE;
//
return TRUE;
}

陈晓猫 2019-08-22
  • 打赏
  • 举报
回复
谢谢回复,能否在一楼代码的基础上补充完善,我想要把这段代码跑起来,需要补充什么头文件,文件输入输出,比如pBuffer怎么定义,怎么用,length又是什么?pText又怎么赋值?我想跑起来。能否直接上代码?望指教下,谢谢了!
schlafenhamster 2019-08-22
  • 打赏
  • 举报
回复
UCS-4 range (hex.) UTF-8 octet sequence (binary)
0000 0000-0000 007F 0xxxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx // 110 表示 2个 字节 一个 UTF-8
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx // 1110 表示 3个 字节 一个 UTF-8

0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx // 11110 表示 4个 字节 一个 UTF-8
0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx // 111110 表示 5个 字节 一个 UTF-8
0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx // 1111110 表示 6个 字节 一个 UTF-8

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧