zxing乱码和变成日文乱码解决,可借鉴

1,236 阅读2分钟

汉字乱码基本都是编码问题导致。根据网上查阅的资料(抄代码)

1.普通乱码,通过重新编码,然后判断是不是符合条件

/**
     * 简单处理下乱码,不一定全好用
     *
     * @param s
     * @return
     */
    public static String processQrCodeString(String s) {
        Charset[] formats = new Charset[]{
                StandardCharsets.UTF_8,
                Charset.forName("GB2312"),
                Charset.forName("GB18030")
        };
        if (!isNormal(s)) {
            try {
                byte[] bytes = s.getBytes(StandardCharsets.ISO_8859_1);
                byte[] bytes2 = s.getBytes("GBK");
                for (Charset charset : formats) {
                    String ss = new String(bytes, charset);
                    if (isNormal(ss)) {
                        return ss;
                    }
                    String ss2 = new String(bytes2, charset);
                    if (isNormal(ss2)) {
                        return ss2;
                    }
                }
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

        }
        return s;
    }

    /**
     * 是否只包含固定一些字符
     *
     * @param str
     * @return
     */
    public static boolean isNormal(String str) {
        if (str.startsWith("\ufeff")) {
            str = str.replace("\ufeff", "");
        }
        char[] charArray = str.toCharArray();
        for (char c : charArray) {
            if ((c >= 32 && c <= 127 && c != 63) || (c >= '\u4e00' && c <= '\u9fa5')/* || (c >= 'A' && c <= 'z')*/) {
                //如果是正常需要的字符:汉字,字母,数字和ascii中的显示自诩,就算正确的,出现不对的,就false
                //可以根据自己需要调整
            } else {
                return false;
            }
        }
        return !isSpecialCharacter(str);
    }

    private static final boolean isSpecialCharacter(String str) {
        //是"�"这个特殊字符的乱码情况
        if (str.contains("�")) {
            return true;
        }
        return false;
    }

之后发现有的扫码后出现日文。。。这个看网上遇到的不多。试了微信是可以正常扫码的,支付宝和京东等不能正常转为中文。 后来参考 这个关于微信扫描二维码出现乱码的bug及其解决方法

在zxingDecoder文件的

rawResult = multiFormatReader.decodeWithState(bitmap);

之前给multiFormatReader设置hints,里面将字符集设置为GBK或者utf-8,我为了能尽量多涵盖点可能性,也许写的有些浪费

@Override
    public Result decode(byte[] data, int dataWidth, int dataHeight, int left, int top, int width, int height) {
        Result rawResult = null;
        PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(data, dataWidth, dataHeight, left, top,
                width, height, false);
        if (source != null) {
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
            try {
                for (String set : new String[]{"utf-8", "GBK"}) {
                    Map<DecodeHintType, Object> hints = new HashMap<>();
                    //----⬇️这里
                    hints.put(DecodeHintType.CHARACTER_SET, set);
                    
                    multiFormatReader.setHints(hints);
                    rawResult = multiFormatReader.decodeWithState(bitmap);
                    if (!StringUtils.isNormal(rawResult.getText())) {
                        String text = StringUtils.processQrCodeString(rawResult.getText());
                        if (StringUtils.isNormal(text)) {
                            return rawResult;
                        }
                    }
                }
            } catch (ReaderException re) {
                // continue
            } finally {
                multiFormatReader.reset();
            }
        }
        return rawResult;
    }

用这两个方法配合,解决了目前的乱码问题。

还有一个问题,如果二维码外没有留白,紧贴着的是黑色的边框,基本扫不到。用zbar解码是没有问题的,不知道该怎么优化zxing,希望大佬们指导。

新账号,第一次写,哈。记录一下,省的以后再碰到