一段のファイルがUTF-8符号化かGB 2312符号化かを判断する

3127 ワード

中国語と英語のみを含むテキストで符号化方式を判断するのは非常に簡単で、中国語の符号化方式で最もよく使われているのはGBKであり、文字セットがより大きく、例えばGBK下互換GB 2312のように、その中に含まれている多くの文字は私たちが日常生活で使用できないので、実際にはGB 2312とUTF 8の符号化を区別するだけである.ここで私はただ実行可能な方法を提供するだけで、GBKを判断しても同様の方法でまずGB 2312における漢字の符号化方式を分析することができ、gb 2312規則漢字は2バイト符号化のうち第1バイト161~247、第2バイト161~254を採用し、その中に境界エントリが含まれている.utf 8の符号化方式は以下のように示すことができる.
 

コード範囲16進数
スカラー値バイナリ
UTF-8バイナリ/16進法
コメント
00000-00007 F 128コード
00000000 00000000 0zzzzzzz
0zzzzzzz(00-7F)
ASCII文字範囲、バイトはゼロから開始
七つのz
七つのz
000080-0007 FF 1920コード
00000000 00000yyy yyzzzzzz
110yyyyy(C0-DF) 10zzzzzz(80-BF)
最初のバイトは110から始まり、次のバイトは10から始まります.
3つのy;二つのy;六つのz
五つy;六つのz
000800-00 D 7 FF 00 E 000-00 FFFFFF 61440個コード[Note 1]
00000000 xxxxyyyy yyzzzzzz
1110xxxx(E0-EF) 10yyyyyy 10zzzzzz
最初のバイトは1110から始まり、次のバイトは10から始まります.
4つのx;4つのy;二つのy;六つのz
4つのx;6個y;六つのz
010000-10 FFFF 1048576コード
000wwwxx xxxxyyyy yyzzzzzz
11110www(F0-F7) 10xxxxxx 10yyyyyy 10zzzzzz
11110から始まり、次のバイトは10から始まります.
これにより、GB 2312とUTF 8の符号化識別を符号化方式の違いによって行うことができ、以下に符号を与える.
unsigned int countGBK(const char * str)
{
	assert(str != NULL);
	unsigned int len = (unsigned int)strlen (str);
    unsigned int counter = 0;
    unsigned char head = 0x80;
	unsigned char firstChar, secondChar;

	for (unsigned int i = 0; i < len - 1; ++i)
	{
		firstChar = (unsigned char)str[i];
		if (!(firstChar & head))continue;
		secondChar = (unsigned char)str[i];
		if (firstChar >= 161 && firstChar <= 247 && secondChar>=161 && secondChar <= 254)
		{
			counter+= 2;
			++i;
		}
	}
	return counter;
}

unsigned int countUTF8(const char * str)
{
	assert(str != NULL);
	unsigned int len = (unsigned int)strlen (str);
    unsigned int counter = 0;
    unsigned char head = 0x80;
	unsigned char firstChar;
	for (unsigned int i = 0; i < len; ++i)
	{
		firstChar = (unsigned char)str[i];
		if (!(firstChar & head))continue;
		unsigned char tmpHead = head;
		unsigned int wordLen = 0 , tPos = 0;
		while (firstChar & tmpHead)
		{
			++ wordLen;
			tmpHead >>= 1;
		}
		if (wordLen <= 1)continue; //utf8     2
		wordLen --;
		if (wordLen + i >= len)break;
		for (tPos = 1; tPos <= wordLen; ++tPos)
		{
			unsigned char secondChar = (unsigned char)str[i + tPos];
			if (!(secondChar & head))break;
		}
		if (tPos > wordLen)
		{
			counter += wordLen + 1;
			i += wordLen;
		}
	}
	return counter;
}

bool beUtf8(const char *str)
{
    	unsigned int iGBK = countGBK(str);
	unsigned int iUTF8= countUTF8(str);
	if (iUTF8 > iGBK)return true;
	return false;
}
countUTF8 countGBK            UTF8   GB2312         ,beUtf8                ,             。
              GB2312     UTF8      ,   C0 C1      UTF8      ,  if (iUTF8 > iGBK)return true;                          ,      ,     “  ”            utf8  。