最近在工作中,遇到了識別二維碼亂碼的問題,由於二維碼編碼結果以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;
}
}