java实现二维码生成与解析

本文介绍如何使用QRCode和ZXing库生成及解析二维码,并提供Java实现示例代码。涵盖不同库的特点、使用方法及参数配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、支持QRcode、ZXing 二维码生成、解析;

2、QRCode 方式生成二维码支持添加图片,如下:




[java]  view plain  copy
  1. package common;  
  2.   
  3. import java.awt.Color;  
  4. import java.awt.Graphics2D;  
  5. import java.awt.Image;  
  6. import java.awt.image.BufferedImage;  
  7. import java.io.File;  
  8. import java.io.IOException;  
  9. import java.util.HashMap;  
  10. import java.util.Map;  
  11.   
  12. import javax.imageio.ImageIO;  
  13.   
  14. import jp.sourceforge.qrcode.QRCodeDecoder;  
  15. import jp.sourceforge.qrcode.exception.DecodingFailedException;  
  16.   
  17. import com.google.zxing.BarcodeFormat;  
  18. import com.google.zxing.Binarizer;  
  19. import com.google.zxing.BinaryBitmap;  
  20. import com.google.zxing.EncodeHintType;  
  21. import com.google.zxing.LuminanceSource;  
  22. import com.google.zxing.MultiFormatReader;  
  23. import com.google.zxing.MultiFormatWriter;  
  24. import com.google.zxing.NotFoundException;  
  25. import com.google.zxing.WriterException;  
  26. import com.google.zxing.common.BitMatrix;  
  27. import com.google.zxing.common.HybridBinarizer;  
  28. import com.swetake.util.Qrcode;  
  29.   
  30. /** 
  31.  * 二维码生成工具类 
  32.  * @author Cloud 
  33.  * @data   2016-12-15 
  34.  * QRCode 
  35.  */  
  36.   
  37. public class QRCodeUtil {  
  38.       
  39.     //二维码颜色  
  40.     private static final int BLACK = 0xFF000000;  
  41.     //二维码颜色  
  42.     private static final int WHITE = 0xFFFFFFFF;  
  43.   
  44.     /** 
  45.      * <span style="font-size:18px;font-weight:blod;">ZXing 方式生成二维码</span> 
  46.      * @param text    <a href="javascript:void();">二维码内容</a> 
  47.      * @param width    二维码宽 
  48.      * @param height    二维码高 
  49.      * @param outPutPath    二维码生成保存路径 
  50.      * @param imageType        二维码生成格式 
  51.      */  
  52.     public static void zxingCodeCreate(String text, int width, int height, String outPutPath, String imageType){  
  53.         Map<EncodeHintType, String> his = new HashMap<EncodeHintType, String>();  
  54.         //设置编码字符集  
  55.         his.put(EncodeHintType.CHARACTER_SET, "utf-8");  
  56.         try {  
  57.             //1、生成二维码  
  58.             BitMatrix encode = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, width, height, his);  
  59.               
  60.             //2、获取二维码宽高  
  61.             int codeWidth = encode.getWidth();  
  62.             int codeHeight = encode.getHeight();  
  63.               
  64.             //3、将二维码放入缓冲流  
  65.             BufferedImage image = new BufferedImage(codeWidth, codeHeight, BufferedImage.TYPE_INT_RGB);  
  66.             for (int i = 0; i < codeWidth; i++) {  
  67.                 for (int j = 0; j < codeHeight; j++) {  
  68.                     //4、循环将二维码内容定入图片  
  69.                     image.setRGB(i, j, encode.get(i, j) ? BLACK : WHITE);  
  70.                 }  
  71.             }  
  72.             File outPutImage = new File(outPutPath);  
  73.             //如果图片不存在创建图片  
  74.             if(!outPutImage.exists())  
  75.                 outPutImage.createNewFile();  
  76.             //5、将二维码写入图片  
  77.             ImageIO.write(image, imageType, outPutImage);  
  78.         } catch (WriterException e) {  
  79.             e.printStackTrace();  
  80.             System.out.println("二维码生成失败");  
  81.         } catch (IOException e) {  
  82.             e.printStackTrace();  
  83.             System.out.println("生成二维码图片失败");  
  84.         }  
  85.     }  
  86.       
  87.     /** 
  88.      * <span style="font-size:18px;font-weight:blod;">二维码解析</span> 
  89.      * @param analyzePath    二维码路径 
  90.      * @return 
  91.      * @throws IOException 
  92.      */  
  93.     @SuppressWarnings({ "rawtypes""unchecked" })  
  94.     public static Object zxingCodeAnalyze(String analyzePath) throws Exception{  
  95.         MultiFormatReader formatReader = new MultiFormatReader();  
  96.         Object result = null;  
  97.         try {  
  98.             File file = new File(analyzePath);  
  99.             if (!file.exists())  
  100.             {  
  101.                 return "二维码不存在";  
  102.             }  
  103.             BufferedImage image = ImageIO.read(file);  
  104.             LuminanceSource source = new LuminanceSourceUtil(image);  
  105.             Binarizer binarizer = new HybridBinarizer(source);    
  106.             BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);  
  107.             Map hints = new HashMap();  
  108.             hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");  
  109.             result = formatReader.decode(binaryBitmap, hints);  
  110.         } catch (NotFoundException e) {  
  111.             e.printStackTrace();  
  112.         }    
  113.         return result;  
  114.     }  
  115.       
  116.     /** 
  117.      * <span style="font-size:18px;font-weight:blod;">QRCode 方式生成二维码</span> 
  118.      * @param content    二维码内容 
  119.      * @param imgPath    二维码生成路径 
  120.      * @param version    二维码版本 
  121.      * @param isFlag    是否生成Logo图片    为NULL不生成 
  122.      */  
  123.     public static void QRCodeCreate(String content, String imgPath, int version, String logoPath){  
  124.          try {    
  125.             Qrcode qrcodeHandler = new Qrcode();    
  126.             //设置二维码排错率,可选L(7%) M(15%) Q(25%) H(30%),排错率越高可存储的信息越少,但对二维码清晰度的要求越小      
  127.             qrcodeHandler.setQrcodeErrorCorrect('M');    
  128.             //N代表数字,A代表字符a-Z,B代表其他字符    
  129.             qrcodeHandler.setQrcodeEncodeMode('B');    
  130.             //版本1为21*21矩阵,版本每增1,二维码的两个边长都增4;所以版本7为45*45的矩阵;最高版本为是40,是177*177的矩阵    
  131.             qrcodeHandler.setQrcodeVersion(version);  
  132.             //根据版本计算尺寸  
  133.             int imgSize = 67 + 12 * (version - 1) ;    
  134.             byte[] contentBytes = content.getBytes("gb2312");    
  135.             BufferedImage bufImg = new BufferedImage(imgSize , imgSize ,BufferedImage.TYPE_INT_RGB);    
  136.             Graphics2D gs = bufImg.createGraphics();    
  137.             gs.setBackground(Color.WHITE);    
  138.             gs.clearRect(00, imgSize , imgSize);    
  139.             // 设定图像颜色 > BLACK  
  140.             gs.setColor(Color.BLACK);  
  141.             // 设置偏移量 不设置可能导致解析出错    
  142.             int pixoff = 2;  
  143.             // 输出内容 > 二维码    
  144.             if (contentBytes.length > 0 && contentBytes.length < 130) {  
  145.                 boolean[][] codeOut = qrcodeHandler.calQrcode(contentBytes);  
  146.                 for (int i = 0; i < codeOut.length; i++) {  
  147.                     for (int j = 0; j < codeOut.length; j++) {  
  148.                         if (codeOut[j][i]) {    
  149.                             gs.fillRect(j * 3 + pixoff, i * 3 + pixoff, 33);  
  150.                         }    
  151.                     }    
  152.                 }    
  153.             } else {    
  154.                 System.err.println("QRCode content bytes length = " + contentBytes.length + " not in [ 0,130 ]. ");    
  155.             }  
  156.            /* 判断是否需要添加logo图片 */  
  157.             if(logoPath != null){  
  158.                 File icon = new File(logoPath);  
  159.                 if(icon.exists()){  
  160.                     int width_4 = imgSize / 4;  
  161.                     int width_8 = width_4 / 2;  
  162.                     int height_4 = imgSize / 4;  
  163.                     int height_8 = height_4 / 2;  
  164.                     Image img = ImageIO.read(icon);  
  165.                     gs.drawImage(img, width_4 + width_8, height_4 + height_8,width_4,height_4, null);  
  166.                     gs.dispose();  
  167.                     bufImg.flush();  
  168.                 }else{  
  169.                     System.out.println("Error: login图片还在在!");  
  170.                 }  
  171.   
  172.             }  
  173.   
  174.   
  175.             gs.dispose();  
  176.             bufImg.flush();  
  177.             //创建二维码文件  
  178.             File imgFile = new File(imgPath);  
  179.             if(!imgFile.exists())  
  180.                 imgFile.createNewFile();  
  181.             //根据生成图片获取图片  
  182.             String imgType = imgPath.substring(imgPath.lastIndexOf(".") + 1, imgPath.length());  
  183.             // 生成二维码QRCode图片    
  184.             ImageIO.write(bufImg, imgType, imgFile);    
  185.          } catch (Exception e) {    
  186.              e.printStackTrace();    
  187.          }  
  188.     }  
  189.       
  190.     /** 
  191.      * <span style="font-size:18px;font-weight:blod;">QRCode二维码解析</span> 
  192.      * @param codePath    二维码路径 
  193.      * @return    解析结果 
  194.      */  
  195.     public static String QRCodeAnalyze(String codePath) {  
  196.         File imageFile = new File(codePath);  
  197.         BufferedImage bufImg = null;    
  198.         String decodedData = null;    
  199.         try {  
  200.             if(!imageFile.exists())  
  201.                 return "二维码不存在";  
  202.             bufImg = ImageIO.read(imageFile);  
  203.             
  204.             QRCodeDecoder decoder = new QRCodeDecoder();    
  205.             decodedData = new String(decoder.decode(new ImageUtil(bufImg)), "gb2312");    
  206.         } catch (IOException e) {    
  207.             System.out.println("Error: " + e.getMessage());    
  208.             e.printStackTrace();    
  209.         } catch (DecodingFailedException dfe) {    
  210.             System.out.println("Error: " + dfe.getMessage());    
  211.             dfe.printStackTrace();    
  212.         }  
  213.         return decodedData;  
  214.     }  
  215.   
  216. }  
  217.   
  218.   
  219. 3、最后贴测试代码:  
  220.   
  221. package test;  
  222.   
  223. import java.awt.image.BufferedImage;  
  224. import java.io.InputStream;  
  225. import java.net.URL;  
  226.   
  227. import javax.imageio.ImageIO;  
  228.   
  229. import common.ImageUtil;  
  230. import common.QRCodeUtil;  
  231.   
  232. import jp.sourceforge.qrcode.QRCodeDecoder;  
  233.   
  234. /** 
  235.  * 二维码生成测试类 
  236.  * @author Cloud 
  237.  * @data   2016-11-21 
  238.  * QRCodeTest 
  239.  */  
  240.   
  241. public class QRCodeTest {  
  242.   
  243.     public static void main(String[] args) throws Exception {  
  244.         /** 
  245.          *    QRcode 二维码生成测试 
  246.          *    QRCodeUtil.QRCodeCreate("http://blog.youkuaiyun.com/u014266877", "E://qrcode.jpg", 15, "E://icon.png"); 
  247.          */  
  248.         /** 
  249.          *     QRcode 二维码解析测试 
  250.          *    String qrcodeAnalyze = QRCodeUtil.QRCodeAnalyze("E://qrcode.jpg"); 
  251.          */  
  252.         /** 
  253.          * ZXingCode 二维码生成测试 
  254.          * QRCodeUtil.zxingCodeCreate("http://blog.youkuaiyun.com/u014266877", 300, 300, "E://zxingcode.jpg", "jpg"); 
  255.          */  
  256.         /** 
  257.          * ZxingCode 二维码解析 
  258.          *    String zxingAnalyze =  QRCodeUtil.zxingCodeAnalyze("E://zxingcode.jpg").toString(); 
  259.          */  
  260.         System.out.println("success");  
  261.     }  
  262. }  


Jar 包下载地址:

http://download.csdn.NET/download/u014266877/9716662


3: 使用BarCode4j生成条形码和二维码 
BarCode4j网址:http://sourceforge.NET/projects/barcode4j/ 

barcode4j是使用datamatrix的二维码生成算法,为支持qr的算法 
datamatrix是欧美的标准,qr为日本的标准, 
barcode4j一般生成出来是长方形的

如:88777alec000yan 
这个博客这方面说的挺清楚的: 
http://baijinshan.iteye.com/blog/1004554


4:google chart api就有实现二维码的方法

    利用这个api,使用google appengine进行实现。

 

5:JS生成二维码

使用jQuery-qrcode生成二维码

先简单说一下jQuery-qrcode,这个开源的三方库(可以从https://github.com/jeromeetienne/jquery-qrcode 获取),

qrcode.js 是实现二维码数据计算的核心类,

jquery.qrcode.js 是把它用jquery方式封装起来的,用它来实现图形渲染,其实就是画图(支持canvas和table两种方式)


支持的功能主要有:

Js代码:

  1. text     : "https://github.com/jeromeetienne/jquery-qrcode"  //设置二维码内容  

     

Js代码:

  1. render   : "canvas",//设置渲染方式   
  2. width       : 256,     //设置宽度   
  3. height      : 256,     //设置高度   
  4. typeNumber  : -1,      //计算模式   
  5. correctLevel    : QRErrorCorrectLevel.H,//纠错等级   
  6. background      : "#ffffff",//背景颜色   
  7. foreground      : "#000000" //前景颜色  

使用方式非常简单

 

Js代码:

  1. jQuery('#output').qrcode({width:200,height:200,correctLevel:0,text:content});  

经过简单实践,

使用canvas方式渲染性能还是非常不错的,但是如果用table方式,性能不太理想,特别是IE9以下的浏览器,所以需要自行优化一下渲染table的方式,这里就不细述了。

其实上面的js有一个小小的缺点,就是默认不支持中文。

这跟js的机制有关系,jquery-qrcode这个库是采用 charCodeAt() 这个方式进行编码转换的,

而这个方法默认会获取它的 Unicode 编码,一般的解码器都是采用UTF-8, ISO-8859-1等方式,

英文是没有问题,如果是中文,一般情况下Unicode是UTF-16实现,长度2位,而UTF-8编码是3位,这样二维码的编解码就不匹配了。

 

解决方式当然是,在二维码编码前把字符串转换成UTF-8,具体代码如下:

  1. function utf16to8(str) {   
  2.     var out, i, len, c;   
  3.     out = "";   
  4.     len = str.length;   
  5.     for(i = 0; i < len; i++) {   
  6.     c = str.charCodeAt(i);   
  7.     if ((c >= 0x0001) && (c <= 0x007F)) {   
  8.         out += str.charAt(i);   
  9.     } else if (c > 0x07FF) {   
  10.         out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));   
  11.         out += String.fromCharCode(0x80 | ((c >>  6) & 0x3F));   
  12.         out += String.fromCharCode(0x80 | ((c >>  0) & 0x3F));   
  13.     } else {   
  14.         out += String.fromCharCode(0xC0 | ((c >>  6) & 0x1F));   
  15.         out += String.fromCharCode(0x80 | ((c >>  0) & 0x3F));   
  16.     }   
  17.     }   
  18.     return out;   
  19. }  



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值