判断文件的字符编码(UTF8和ANSI)

最近在用C++做XML解析的小实验,其他语言,比如JAVA,PY都有判断文件编码的类,所以我就想用C++做个类似的功能。弄了几天终于做出来了,代码如下:

bool Text::IsUTF8(const char* szBuffer)
{
	//判断高位到低位有多少个1,UTF-8的字符是有规律的
	//在UTF8中,如果中文字符占3位,那么首字节的编码一定是十六进制的E开头,过3个字节又是E开头
	//可以通过这个规律来判断文件的字符编码,在ANSI编码中,中文是固定两个字节的,没有规律,
	//同时windows的简体中文都是采用的ANSI中的GB2312编码,通过cmd查看代码页可以看出
	//对于英文这种单字节的编码,UTF8和GB2312编码一样
	//windows是根据操作系统的语言来判断使用什么编码来解析文件,当然我现在使用的win10记事本默认编码
	//是UTF8,以前的记事本默认是ANSI,所以过去会出现从网络上下载的txt文件乱码

	bool IsUtf8 = true;
    
	//先读取文件中的英文字符的个数
	//就是那每个字节的编码与0x80相与(&)判断最高位是不是0,如果是0就是英文字符,如果是1的话肯定是中文字符
	int start = 0;
	int end = m_length; //这个长度没有带上char字符组后面的'\0'
	int EngNums = 0;
	int ChineseNums = 0; //这统计的是字节不是字符个数,因为现在还不清楚中文所占的字节数
	vector<int> posChinese;//存放中文字节位置
	while (start < end)
	{
		int out = m_binaryStr[start] & 0x80;
		int isEng = this->Num(out);//判断高位是1还是0
		if (isEng == 0)
			EngNums++;
		else
		{
			ChineseNums++;
			posChinese.push_back(start); //保存中文字符位置
		}
			
		start++;
	}
	//cout << "中文字符所占的字节有" << ChineseNums << "个"<<endl;
	//cout << "英文字符所占的字节有" << EngNums << "个" << endl;

	//接下来先把英文字符减掉,不管在UTF8和ANSI英文都只占一个字节
	int newLength = m_length - EngNums;
	//剩下的字节用来除以3和2,如果能整除3那就说明是UTF8编码,否则就是ANSI编码
	//这有一个问题,那就是如果出现3,2的公倍数那就无法判断,比如说两个文件除去英文字符后都是6字节
	//当出现这种情况后,则需要判断中文字符的字节特点,特点如上
	bool isTrue = false;  //给个标志位,防止重复判断
	if (newLength % 3 == 0)
	{
		if (newLength % 2 == 0)
		{
			isTrue = true; //已经判断了,下面判断整除2的就不用了
			//使用0xE0(11100000)进行判断
			start = 0;
			while (start < posChinese.size())
			{
				int out = m_binaryStr[posChinese.at(start)] & 0xE0;//如果是UTF8的中文字符,这个的结果是11100000就是0xE0
				if (out == 0xE0)
				{
					start += 3;//向后移动3个字节
				}
				else//一旦发现中文字符的首字节中前3位没有111就是ANSI编码
				{
					return false;
				}
			}

		}
		
		return true;

	}

	if (newLength % 2 == 0&&isTrue==false)//只能被2整除的话
	{
	
		//cout << "ANSI" << endl;
		return false;

	}
	return IsUtf8;
}

由于我是将他写在一个类中,所以函数中的m_length和m_binaryStr字符数组是我通过C++的库函数中的filebuf获得的,Num函数是统计十进制转到二进制后从高位开始有多少个连续的1,这个函数学过C的都知道。其他的一些方法我都在注释里写的很清楚了。欢迎大家来一起交流。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DreamXY12

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值