如題,對某些內容進行解析時造成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包的問題。
