Zxing3.2.1 之前遇到过Android Zxing扫码乱码的问题,网上搜了下解决了下。 今天又遇到了问题。 依然会乱码。
研究总结如下:
Zxing 可以在Hints中添加默认编码格式。这个编码格式是用于解读Byte数据时,
1.如果码中没有指定编码集则,默认使用该编码格式。
2.如果制定了编码集,则使用编码指定的字符集。
并非强制 ,而中文的主要编码格式有两种,GBK 和UTF-8。
注意,网上有很多提到“ISO-8859-1”这个编码集的,这个编码集是个简单编码集,每个字节一个字符。并不是一个能表示中文的编码集。
有些情况可以利用他的单字节字符特性,进行字节和字符的互转。
但因为上面规则2的存在,使用这个编码集做byte取得的多多少少都有点问题。(如指明UTF-8编码的,则返回结果已经是utf8,用ISO8859取得bytes反儿会乱码,因为ISO无法表示UTF-8的字符,会替换为?号)。
因为,码生成不同,会包含是否指明编码格式两种情况,而编码本身又可能是Utf8或者GBK,而进行String转换的过程中,二进制信息会丢失。
因此思路上,如果可以取得原始的byte数组,就可以判断用正确的字符集显示了。应避免通过String转换取得。
解决也比较简单,看了下源码,发现其实扫码结果中本来就包含了这些信息。
//源码 QRCodeReader public final Result decode(BinaryBitmap image, Map<DecodeHintType,?> hints)方法中
//向Result Metadata中放了一些额外信息。这是一个Map
……
result.putMetadata(ResultMetadataType.BYTE_SEGMENTS,byteSegments);
……
这个result就是扫码结果result。 在实例中会在MipcaActivityCapture的扫码结果回调
public void handleDecode(Result result, Bitmap barcode)
byteSegments记录了原始二进制数据,直接判断二进制数据格式即可。
List<byte[]> byteSegments = (List<byte[]>) result.getResultMetadata().get(ResultMetadataType.BYTE_SEGMENTS);
StringBuffer buffer1 =new StringBuffer();
for (int i = 0; i < byteSegments.size(); i++) {
byte[] buffer =byteSegments.get(i);
String tempStr = "";
//猜一下编码格式
if(isUtf8(buffer)){
tempStr = new String(buffer, "utf-8");
}else{
tempStr = new String(buffer, "GBK");
}
buffer1.append(tempStr);
}
resultString = buffer1.toString();
isUtf8 是网上抄来的一个工具函数,如下
public static Boolean isUtf8(byte[] buffer) {
boolean isUtf8 = true;
int end = buffer.length;
for (int i = 0; i < end; i++) {
byte temp = buffer[i];
if ((temp & 0x80) == 0) {// 0xxxxxxx
continue;
} else if ((temp & 0xC0) == 0xC0 && (temp & 0x20) == 0) {// 110xxxxx 10xxxxxx
if (i + 1 < end && (buffer[i + 1] & 0x80) == 0x80 && (buffer[i + 1] & 0x40) == 0) {
i = i + 1;
continue;
}
} else if ((temp & 0xE0) == 0xE0 && (temp & 0x10) == 0) {// 1110xxxx 10xxxxxx 10xxxxxx
if (i + 2 < end && (buffer[i + 1] & 0x80) == 0x80 && (buffer[i + 1] & 0x40) == 0
&& (buffer[i + 2] & 0x80) == 0x80 && (buffer[i + 2] & 0x40) == 0) {
i = i + 2;
continue;
}
} else if ((temp & 0xF0) == 0xF0 && (temp & 0x08) == 0) {// 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
if (i + 3 < end && (buffer[i + 1] & 0x80) == 0x80 && (buffer[i + 1] & 0x40) == 0
&& (buffer[i + 2] & 0x80) == 0x80 && (buffer[i + 2] & 0x40) == 0
&& (buffer[i + 3] & 0x80) == 0x80 && (buffer[i + 3] & 0x40) == 0) {
i = i + 3;
continue;
}
}
isUtf8 = false;
break;
}
return isUtf8;
}
View Code问题解决。
本文来自博客园,作者:Uncle锅
转载请注明原文链接:https://www.cnblogs.com/uncleguo/p/15981253.html