Shun 发表于 2022-3-9 10:21:18

真·Android Zxing 扫码中文乱码解决

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;
            if ((temp & 0x80) == 0) {// 0xxxxxxx
                continue;
            } else if ((temp & 0xC0) == 0xC0 && (temp & 0x20) == 0) {// 110xxxxx 10xxxxxx
                if (i + 1 < end && (buffer & 0x80) == 0x80 && (buffer & 0x40) == 0) {
                  i = i + 1;
                  continue;
                }
            } else if ((temp & 0xE0) == 0xE0 && (temp & 0x10) == 0) {// 1110xxxx 10xxxxxx 10xxxxxx
                if (i + 2 < end && (buffer & 0x80) == 0x80 && (buffer & 0x40) == 0
                        && (buffer & 0x80) == 0x80 && (buffer & 0x40) == 0) {
                  i = i + 2;
                  continue;
                }
            } else if ((temp & 0xF0) == 0xF0 && (temp & 0x08) == 0) {// 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
                if (i + 3 < end && (buffer & 0x80) == 0x80 && (buffer & 0x40) == 0
                        && (buffer & 0x80) == 0x80 && (buffer & 0x40) == 0
                        && (buffer & 0x80) == 0x80 && (buffer & 0x40) == 0) {
                  i = i + 3;
                  continue;
                }
            }
            isUtf8 = false;
            break;
      }
      return isUtf8;
    }View Code问题解决。

本文来自博客园,作者:Uncle锅
转载请注明原文链接:https://www.cnblogs.com/uncleguo/p/15981253.html


   
   
   
                        

https://www.cnblogs.com/uncleguo/p/15981253.html
页: [1]
查看完整版本: 真·Android Zxing 扫码中文乱码解决