如题,对某些内容进行解析时造成NotFoundException异常,而在对大多数内容进行解析时不会造成错误。
首先来看一看解析的代码
BufferedImage image = ImageIO.read(new File(path)); if (image == null) { return null; } BarcodeLuminanceSource source = new BarcodeLuminanceSource(image); BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>(); hints.put(DecodeHintType.CHARACTER_SET, controler.getEncode()); Result result = new MultiFormatReader().decode(bitmap, hints); String code = result.getText(); byte[] bytes = IOUtils.toByteArray(new FileInputStream(new File(path))); ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
其中BarcodeLuminanceSource是自定义的一个继承自LuminanceSource类,代码从网上借鉴来的。
当执行到new MulitiFormatReader().decode(bitmap,hints)就会报错。
比如在对内容【http://192.168.0.102:9080/rencongums】进行编码解码会报错,而对【http://localhost:9080/rencongums】进行编码解码就不会报错。
最开始还以为是自定义BarcodeLuminanceSource的问题,于是换成了
<!-- https://mvnrepository.com/artifact/com.google.zxing/javase --> <dependency> <groupId>com.google.zxing</groupId> <artifactId>javase</artifactId> <version>3.2.1</version> </dependency>
中的BufferedImageLuminanceSource,但是依然没有解决问题,于是又以为是添加了Logo的原因,去除之后依然会抛出异常。目前还没有查明原因。
根据打断点进去会发现,调用decode的时候会有如下几个Decoder
readers.add(new MultiFormatOneDReader(hints)); readers.add(new QRCodeReader()); readers.add(new DataMatrixReader()); readers.add(new AztecReader()); readers.add(new PDF417Reader()); readers.add(new MaxiCodeReader());
而其中此处需要的是DataMatrixReader(),打进去就是会用到 public Result decode(BinaryBitmap image, Map<DecodeHintType,?> hints)这个方法
如图所示:
public Result decode(BinaryBitmap image, Map<DecodeHintType,?> hints) throws NotFoundException, ChecksumException, FormatException { DecoderResult decoderResult; ResultPoint[] points; if (hints != null && hints.containsKey(DecodeHintType.PURE_BARCODE)) { BitMatrix bits = extractPureBits(image.getBlackMatrix()); decoderResult = decoder.decode(bits); points = NO_POINTS; } else { DetectorResult detectorResult = new Detector(image.getBlackMatrix()).detect(); decoderResult = decoder.decode(detectorResult.getBits()); points = detectorResult.getPoints(); } Result result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), points, BarcodeFormat.DATA_MATRIX); List<byte[]> byteSegments = decoderResult.getByteSegments(); if (byteSegments != null) { result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments); } String ecLevel = decoderResult.getECLevel(); if (ecLevel != null) { result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel); } return result; }
里面就调用了decoder.decode(bits);方法
如下图所示:
public DecoderResult decode(BitMatrix bits) throws FormatException, ChecksumException { // Construct a parser and read version, error-correction level BitMatrixParser parser = new BitMatrixParser(bits); Version version = parser.getVersion(); // Read codewords byte[] codewords = parser.readCodewords(); // Separate into data blocks DataBlock[] dataBlocks = DataBlock.getDataBlocks(codewords, version); int dataBlocksCount = dataBlocks.length; // Count total number of data bytes int totalBytes = 0; for (DataBlock db : dataBlocks) { totalBytes += db.getNumDataCodewords(); } byte[] resultBytes = new byte[totalBytes]; // Error-correct and copy data blocks together into a stream of bytes for (int j = 0; j < dataBlocksCount; j++) { DataBlock dataBlock = dataBlocks[j]; byte[] codewordBytes = dataBlock.getCodewords(); int numDataCodewords = dataBlock.getNumDataCodewords(); correctErrors(codewordBytes, numDataCodewords); for (int i = 0; i < numDataCodewords; i++) { // De-interlace data blocks. resultBytes[i * dataBlocksCount + j] = codewordBytes[i]; } } // Decode the contents of that stream of bytes return DecodedBitStreamParser.decode(resultBytes); }
里面可以看到调用了 correctErrors(codewordBytes, numDataCodewords);方法
private void correctErrors(byte[] codewordBytes, int numDataCodewords) throws ChecksumException { int numCodewords = codewordBytes.length; // First read into an array of ints int[] codewordsInts = new int[numCodewords]; for (int i = 0; i < numCodewords; i++) { codewordsInts[i] = codewordBytes[i] & 0xFF; } int numECCodewords = codewordBytes.length - numDataCodewords; try { rsDecoder.decode(codewordsInts, numECCodewords); } catch (ReedSolomonException ignored) { throw ChecksumException.getChecksumInstance(); } // Copy back into array of bytes -- only need to worry about the bytes that were data // We don't care about errors in the error-correction codewords for (int i = 0; i < numDataCodewords; i++) { codewordBytes[i] = (byte) codewordsInts[i]; } }
显然对于某些特殊的字符串来说完全可能由于checksum不通过而造成抛出异常,因此这是zxing包的问题。