識別字符數組編碼類型

        最近在工作中,遇到了識別二維碼亂碼的問題,由於二維碼編碼結果以byte數組的形式給出,並不知道解析的是那種編碼,會導致由於字符編碼不正確導致的亂碼問題,網上找的開源方案有時候會誤識別,正確率不高,一直想找個機會做一個識別編碼的工具,那麼現在就開始吧。

先做一個識別utf-8的工具類,參考 http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

根據編碼規則來做

Unicode符號範圍     |        UTF-8編碼方式
(十六進制)        |              (二進制)
----------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
以下是實現代碼
public class DecodeType {
	public static String utf8 = "utf-8", gb2312 = "gb2312",
			gbk18030 = "gbk18030";

	public String guess(byte[] b) {
		String defaultCharSetName = "default";
		String charSetName = defaultCharSetName;
		if (isUTF8(b))
			charSetName = utf8;
		if (isGB2312(b))
			charSetName = gb2312;
		return charSetName;
	}


	public boolean isGB2312(byte[] b) {
		boolean isgb2312 = false;
		for (int i=0;i<b.length;i++) {
			if ((b[i] & 0xff) < 0xa0&&(b[++i]&0xff)<0x0a) {
				isgb2312 = false;
				break;
			} else {
				isgb2312 = true;
			}
		}
		return isgb2312;
	}

	public boolean isUTF8(byte[] b) {
		boolean isutf8 = false;
		for (int i = 0; i < b.length; i++) {
			int bzc = beforeZeroCount(b[i]);
			if (bzc >= 2) {// 判斷存在第一個不是0的byte的後面幾個byte是否符合utf8編碼規則
				for (int j = 1; j < (bzc - 1); j++) {
					if (i + j >= b.length) {
						isutf8 = false;
						break;
					}
					if (beforeZeroCount(b[i + j]) == 0) {
						isutf8 = false;
						break;
					} else {
						isutf8 = true;
					}
				}
			}
		}
		return isutf8;
	}

	public int beforeZeroCount(byte b) {// 計算從高位到低位,第一個0之前有幾位
		int count = 0;
		for (int i = 0; i < 8; i++) {
			if (((b & (128 >> i)) == 0)) {
				break;
			} else {
				count++;
			}
		}
		return count;
	}

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章