二维码的生成方法网上一搜一大堆,但基本都是直接以字符串进行生成,存储访问路径或一些简单的信息。然而有时就是有这么特殊的需求,需要使用二维码传输数据,数据量还比较大。数据量太大二维码不好生成和扫描,就想到压缩数据,使用jdk的GZIP压缩,得到一个byte数组。byte数组无法生成二维码,直接new String()转回字符串,看下数据量比压缩前还大,base64编码一下,虽然比压缩前小,但是比编码前大多了。那么是否可以直接使用数组生成二维码呢?

改写的jar:重新编译的可使用byte[]生成二维码的zxing-core-3.4.0
使用方法:java压缩字符串并生成二维码

二维码生成

对zxing的core-3.4.0源码进行追踪、查看,new MultiFormatWriter().encode()选择生成QRCode。

我们要生成QRCode,其它的生成方式就不需要,直接改写为:

public BitMatrix encodeQRCode(byte[] contents, int width, int height, Map<EncodeHintType,?> hints) throws WriterException {QRCodeWriter writer = new QRCodeWriter();return writer.encodeQRCode(contents, width, height, hints);}

追踪进入QRCodeWriter的encode方法。

这里主要是对参数的验证,只需要把encode方法改为我们自定义的encodeQRCode方法:

public BitMatrix encodeQRCode(byte[] contents, int width, int height, Map<EncodeHintType,?> hints) throws WriterException {if (contents == null || contents.length == 0) {throw new IllegalArgumentException("Found empty contents");}if (width < 0 || height < 0) {throw new IllegalArgumentException("Requested dimensions are too small: " + width + 'x' +height);}ErrorCorrectionLevel errorCorrectionLevel = ErrorCorrectionLevel.L;int quietZone = QUIET_ZONE_SIZE;if (hints != null) {if (hints.containsKey(EncodeHintType.ERROR_CORRECTION)) {errorCorrectionLevel = ErrorCorrectionLevel.valueOf(hints.get(EncodeHintType.ERROR_CORRECTION).toString());}if (hints.containsKey(EncodeHintType.MARGIN)) {quietZone = Integer.parseInt(hints.get(EncodeHintType.MARGIN).toString());}}QRCode code = Encoder.encodeQRCode(contents, errorCorrectionLevel, hints);return renderResult(code, width, height, quietZone);}

继续追踪进入Encoder的encode方法。

去掉一些不需要的验证,把appendBytes方法改写:

public static QRCode encodeQRCode(byte[] content, ErrorCorrectionLevel ecLevel,Map<EncodeHintType,?> hints) throws WriterException {// Pick an encoding mode appropriate for the content. Note that this will not attempt to use// multiple modes / segments even if that were more efficient. Twould be nice.Mode mode = Mode.BYTE;// This will store the header information, like mode and// length, as well as "header" segments like an ECI segment.BitArray headerBits = new BitArray();// Append the FNC1 mode header for GS1 formatted data if applicableboolean hasGS1FormatHint = hints != null && hints.containsKey(EncodeHintType.GS1_FORMAT);if (hasGS1FormatHint && Boolean.valueOf(hints.get(EncodeHintType.GS1_FORMAT).toString())) {// GS1 formatted codes are prefixed with a FNC1 in first position mode headerappendModeInfo(Mode.FNC1_FIRST_POSITION, headerBits);}// (With ECI in place,) Write the mode markerappendModeInfo(mode, headerBits);// Collect data within the main segment, separately, to count its size if needed. Don't add it to// main payload yet.BitArray dataBits = new BitArray();for (byte b : content) {dataBits.appendBits(b, 8);}//二维码的版本从21×21至177×177总共有40个版本,不同的版本可编码的总数据量不同,不指定则自行根据输入的数据量选择最适合的版本。Version version;if (hints != null && hints.containsKey(EncodeHintType.QR_VERSION)) {int versionNumber = Integer.parseInt(hints.get(EncodeHintType.QR_VERSION).toString());version = Version.getVersionForNumber(versionNumber);int bitsNeeded = calculateBitsNeeded(mode, headerBits, dataBits, version);if (!willFit(bitsNeeded, version, ecLevel)) {throw new WriterException("Data too big for requested version");}} else {version = recommendVersion(ecLevel, mode, headerBits, dataBits);}BitArray headerAndDataBits = new BitArray();headerAndDataBits.appendBitArray(headerBits);// Find "length" of main segment and write itint numLetters = dataBits.getSizeInBytes();appendLengthInfo(numLetters, version, mode, headerAndDataBits);// Put data together into the overall payloadheaderAndDataBits.appendBitArray(dataBits);Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel);int numDataBytes = version.getTotalCodewords() - ecBlocks.getTotalECCodewords();// Terminate the bits properly.terminateBits(numDataBytes, headerAndDataBits);// Interleave data bits with error correction code.BitArray finalBits = interleaveWithECBytes(headerAndDataBits,version.getTotalCodewords(),numDataBytes,ecBlocks.getNumBlocks());QRCode qrCode = new QRCode();qrCode.setECLevel(ecLevel);qrCode.setMode(mode);qrCode.setVersion(version);//  Choose the mask pattern and set to "qrCode".int dimension = version.getDimensionForVersion();ByteMatrix matrix = new ByteMatrix(dimension, dimension);int maskPattern = chooseMaskPattern(finalBits, ecLevel, version, matrix);qrCode.setMaskPattern(maskPattern);// Build the matrix and set it to "qrCode".MatrixUtil.buildMatrix(finalBits, ecLevel, version, maskPattern, matrix);qrCode.setMatrix(matrix);return qrCode;}

appendBytes方法实际上是调用了append8BitBytes方法(纯英文、数字、日语汉字不是),上面重写的方法中直接把append8BitBytes方法内的代码复制了进去,appendBytes的具体代码不贴了,append8BitBytes方法代码如下:

从这里可以看到,字符串实际上最终是转成了byte数组,所以我们直接传byte数组是可以的。

二维码解码

二维码生成完了接下来就是解码了,new MultiFormatReader().decode()返回Result对象,不要使用Result对象的getText方法获取数据,会把byte数组直接转成String,使用rawBytes方法获取byte数组,
byte数组含有zxing在生成二维码时附加的一些信息,需要进行解析获取原始的byte数组。对zxing源码进行分析,实际是可以直接获取到原始的byte数组的,zxing的代码不贴了,MultiFormatReader中把decode改写:

public Result decodeQRCode(BinaryBitmap image, Map<DecodeHintType,?> hints) throws NotFoundException {QRCodeReader reader = new QRCodeReader();this.readers = new Reader[] {reader};try {return  reader.decodeQRCode(image, hints);} catch (Exception e) {e.printStackTrace();}throw NotFoundException.getNotFoundInstance();}

进入QRCodeReader把decode改写:

public final Result decodeQRCode(BinaryBitmap image, Map<DecodeHintType,?> hints) throws NotFoundException, ChecksumException, FormatException {DetectorResult detectorResult = new Detector(image.getBlackMatrix()).detect(hints);DecoderResult decoderResult = decoder.decode(detectorResult.getBits(), hints);return new Result(decoderResult.getText(), decoderResult.getByteSegments().get(0), detectorResult.getPoints(), BarcodeFormat.QR_CODE);}

改写完就可以直接使用Result.getRawBytes()获取原始byte数组了,这里实际上就是Result的rawBytes
本应接收decoderResult.getRawBytes(),替换为了decoderResult.getByteSegments().get(0),decoderResult.getByteSegments().get(0)就是原始的byte数组。

为了不影响原有功能,所有的改写都是新建的方法。

zxing使用byte数组生成二维码和解析二维码相关推荐

  1. 利用ZXing工具生成二维码以及解析二维码

    今天突然想到二维码是如何存储信息的.于是就开始各种搜索,最终自己也利用Google的ZXing工具完成了一个生成二维码和解析二维码的简单程序. 一. 二维码生成原理(即工作原理) 二维码官方叫版本Ve ...

  2. Java利用Zxing生成二维码及解析二维码内容

    前言 Java 操作二维码的开源项目很多,如 SwetakeQRCode.BarCode4j.Zxing 等等 本篇文章是介绍利用Zxing来生成二维码图片在web网页上展示,同时解析二维码图片. Z ...

  3. llqrcode.js识别二维码,解析二维码信息

    llqrcode.js具有扫描二维码功能,用来进行从图片中识别二维码,可解析二维码的信息. 直接上代码 <!DOCTYPE html> <html> <head>& ...

  4. zxing生成二维码及解析二维码

    ZXing生成二维码 1.下载jar https://github.com/ZF520/QRCode/raw/master/zxing/bin/lib/zxing3.3.1.jar 2.生成二维码的函 ...

  5. 【zxing生成二维码及解析二维码】

    导入依赖 <!-- https://mvnrepository.com/artifact/com.google.zxing/core --><dependency><gr ...

  6. java 生成二维码,解析二维码

    今天遇到需求,使用Java生成二维码图片,网搜之后,大神们早就做过,个人总结一下. 目标:借助Google提供的ZXing Core工具包,使用Java语言实现二维码的生成和解析. 步骤如下: 1.m ...

  7. java生成二维码/java解析二维码

    二维码的优缺点 优点:1. 高密度编码,信息容量大:2.编码范围广:3.容错能力强:4.译码可靠性高:5.可引入加密措施:6.成本低,易制作,持久耐用. 缺点:1.二维码技术成为手机病毒.钓鱼网站传播 ...

  8. QRCode生成二维码和解析二维码

    使用QRCode生成和解析二维码,这个和前面的不一样,只要盗图两个jar(后面上传),即可生成二维码 直接上代码,注释都有 Qrcode qrcode=new Qrcode();qrcode.setQ ...

  9. xing生成二维码与解析二维码

    //用xing方式生成二维码public void XingGet(){int width=300;int height=300;String format="png";Strin ...

最新文章

  1. uniapp启动页,底部虚拟按钮向上闪一下的问题
  2. 网络工具中的瑞士军刀——netcat工具简介
  3. php中url编码地址栏,php url地址栏传中文乱码解决方法集合_PHP
  4. mongo笔记 // 一字一句的写下来,工作点滴片段
  5. kitten编程猫里的工具函数
  6. html如何在画布上加层,在Canvas中嵌套Html
  7. nginx重启、关闭
  8. 机器学习——特征工程之特征选择
  9. [转载] 七龙珠第一部——第019话 天下第一武道会开始
  10. 遭遇Asp.Net长文件名下载的问题和解决办法
  11. Atitit sumdoc everything index tech and index log 目录 1. 使用的tech 1 1.1. Atitit 日志记录的三个trace跟踪等级文件夹级
  12. jboss7 应用详解_【扔掉说明书114】本田 思域 2020款 舒适与娱乐功能详解
  13. 运维工程师mysql面试题及答案_系统运维工程师面试题及参考答案
  14. PR转场插件 MAC版 FilmImpact Transition Pack v1-v2
  15. 计算机是如何储存信息的,计算机是如何储存信息的
  16. 分页 在mybatis执行SQL语句之前进行拦击处理实例
  17. 还记得JavaWeb中的组件Servlet吗?面试会问
  18. Ubuntu下使用ipmsg(飞鸽传书)
  19. 工作流管理系统的简单介绍
  20. 天龙日梅兰竹菊_天龙后传:段誉迎娶梅兰竹菊,虚竹怀恨在心,兄弟二人大打出手!...

热门文章

  1. apply、call、bind三者的区别—附:防抖、节流函数
  2. Spark 进程模型与分布式部署:什么是分布式计算?
  3. 基于Java+SpringBoot+Vue前后端分离学生管理系统设计与实现
  4. 二叉搜索树(BinarySearchTree)
  5. 相控阵天线(十):波束跃度、虚位技术、幅度相位误差分析(含代码)
  6. java pushlet_pushlet 之 官方示例解读与改造
  7. iPhone手机最受欢迎的4个APP,拥有这些让你的iOS 12发挥到极致!
  8. matlab角度和弧度的互换_MATLAB弧度与角度转换.docx
  9. 微博展开对违规内容整治;聚美优品CFO辞职;传滴滴拟5亿美元投入青桔单车丨价值早报...
  10. 网易考拉海购更名网易考拉 全面进军综合电商市场