本文是学习慕课网课程《Java生成二维码》(http://www.imooc.com/learn/531)的笔记。
一、二维码的分类
线性堆叠式二维码、矩阵式二维码、邮政码。
二、二维码的优缺点
优点:1. 高密度编码,信息容量大;2.编码范围广;3.容错能力强;4.译码可靠性高;5.可引入加密措施;6.成本低,易制作,持久耐用。
缺点:1.二维码技术成为手机病毒、钓鱼网站传播的新渠道;2.信息容易泄露。
三、三大国际标准
1.PDF417:不支持中文;
2.DM:专利未公开,需要支付专利费用;
3.QR Code:专利公开,支持中文。
其中,QR Code具有识读速度快、数据密度大、占用空间小的优势。
四、纠错能力
L级:约可纠错7%的数据码字
M级:约可纠错15%的数据码字
Q级:约可纠错25%的数据码字
H级:约可纠错30%的数据码字
五、ZXing生成/读取二维码
首先,下载ZXing源文件。下载地址:https://github.com/zxing/zxing/releases;
再次,创建一个Java项目。将ZXing源文件中的core/src/main/java/com和javase/src/main/java/com两个文件复制到项目中,编译成jar文件;
最后,在以后的开发中就可以使用该jar文件。
ZXing生成二维码的代码如下:
1 import java.io.File; 2 import java.nio.file.Path; 3 import java.util.HashMap; 4 5 import com.google.zxing.BarcodeFormat; 6 import com.google.zxing.EncodeHintType; 7 import com.google.zxing.MultiFormatWriter; 8 import com.google.zxing.WriterException; 9 import com.google.zxing.client.j2se.MatrixToImageWriter; 10 import com.google.zxing.common.BitMatrix; 11 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; 12 13 //生成二维码 14 public class CreateQRCode { 15 16 public static void main(String[] args) { 17 int width = 300; //二维码宽度 18 int height = 300; //二维码高度 19 String format = "png"; //二维码图片格式 20 String content = "www.baidu.com"; //二维码内容 21 22 //定义二维码参数 23 HashMap hints = new HashMap(); 24 hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); //定义内容字符集的编码 25 hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); //定义纠错等级 26 hints.put(EncodeHintType.MARGIN, 2); //边框空白 27 28 try { 29 BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height); 30 31 Path file = new File("E:/img.png").toPath(); 32 33 MatrixToImageWriter.writeToPath(bitMatrix, format, file); 34 //MatrixToImageWriter.writeToStream(bitMatrix, format, stream); 35 36 } catch (Exception e) { 37 e.printStackTrace(); 38 } 39 } 40 }
ZXing读取二维码信息的代码如下:
1 import java.awt.image.BufferedImage; 2 import java.io.File; 3 import java.io.IOException; 4 import java.util.HashMap; 5 6 import javax.imageio.ImageIO; 7 8 import com.google.zxing.Binarizer; 9 import com.google.zxing.BinaryBitmap; 10 import com.google.zxing.EncodeHintType; 11 import com.google.zxing.LuminanceSource; 12 import com.google.zxing.MultiFormatReader; 13 import com.google.zxing.NotFoundException; 14 import com.google.zxing.Result; 15 import com.google.zxing.client.j2se.BufferedImageLuminanceSource; 16 import com.google.zxing.common.BitArray; 17 import com.google.zxing.common.BitMatrix; 18 import com.google.zxing.common.HybridBinarizer; 19 20 public class ReadQRCode { 21 22 public static void main(String[] args) { 23 24 try { 25 MultiFormatReader formatReader = new MultiFormatReader(); 26 27 File file = new File("E:/img.png"); 28 29 BufferedImage image = ImageIO.read(file); //读取此文件识别成一个图片 30 31 BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(image))); 32 33 //定义二维码参数 34 HashMap hints = new HashMap(); 35 hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); //定义内容字符集的编码 36 37 38 Result result = formatReader.decode(binaryBitmap,hints); 39 40 System.out.println("解析结果:" + result.toString()); 41 System.out.println("二维码格式类型:" + result.getBarcodeFormat()); 42 System.out.println("二维码文本内容:" + result.getText()); 43 } catch (Exception e) { 44 e.printStackTrace(); 45 } 46 } 47 }
六、QRCode生成/读取二维码
QRCode生成和读取二维码的jar是分开的,下载网址如下:
QRCode生成二维码网址:http://swetake.com/qrcode/index-e.html
QRCode读取二维码网址:https://osdn.jp/projects/qrcode (此网站无法下载到jar文件)
(后面我在网上搜到一个包含生成和读取二维码功能的jar文件,下载路径:https://files.cnblogs.com/files/bigroc/QRCode.zip)
QRCode生成二维码代码如下:
1 import java.awt.Color; 2 import java.awt.Graphics2D; 3 import java.awt.image.BufferedImage; 4 import java.io.File; 5 import java.io.IOException; 6 import java.io.UnsupportedEncodingException; 7 8 import javax.imageio.ImageIO; 9 10 import com.swetake.util.Qrcode; 11 12 //生成二维码 13 public class CreateQRCode { 14 15 public static void main(String[] args) throws IOException { 16 17 //计算二维码图片的高宽比 18 //API文档规定计算图片宽高的方式,v是版本号(1~40) 19 int v = 7; 20 int width = 67 + 12 * (v - 1); //计算公式 21 int height = 67 + 12 * (v - 1); 22 23 Qrcode x = new Qrcode(); 24 25 /** 26 * 纠错等级分为 27 * level L : 最大 7% 的错误能够被纠正; 28 * level M : 最大 15% 的错误能够被纠正; 29 * level Q : 最大 25% 的错误能够被纠正; 30 * level H : 最大 30% 的错误能够被纠正; 31 */ 32 x.setQrcodeErrorCorrect('L'); //设置纠错等级 33 x.setQrcodeEncodeMode('B'); //N代表数字 A代表a-Z B代表其他字符 34 x.setQrcodeVersion(v); //版本号(1~40) 35 String qrData = "http://www.baidu.com"; //内容信息 36 37 //缓冲区 38 BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 39 40 //绘图 41 Graphics2D gs = bufferedImage.createGraphics(); 42 43 gs.setBackground(Color.WHITE); //背景色 44 gs.setColor(Color.black); 45 gs.clearRect(0, 0, width, height); //清除画板内容 46 47 //偏移量 2或7 48 int pixoff = 2; 49 50 /** 51 * 1.注意for循环里面的i,j的顺序, 52 * s[j][i]二维数组的j,i的顺序要与这个方法中的 gs.fillRect(j*3+pixoff,i*3+pixoff, 3, 3); 53 * 顺序匹配,否则会出现解析图片是一串数字 54 * 2.注意此判断if (d.length > 0 && d.length < 120) 55 * 是否会引起字符串长度大于120导致生成代码不执行,二维码空白 56 * 根据自己的字符串大小来设置此配置 57 */ 58 //把要填充的内容转化成字节数 59 byte[] d = qrData.getBytes("utf-8"); //汉字转化格式 60 if (d.length > 0 && d.length < 120) { 61 boolean[][] s = x.calQrcode(d); 62 63 for (int i = 0; i < s.length; i++) { 64 for (int j = 0; j < s.length; j++) { 65 if (s[j][i]) { 66 //把d中的内容填充 67 gs.fillRect(j * 3 + pixoff, i * 3 + pixoff, 3, 3); 68 } 69 } 70 } 71 } 72 73 gs.dispose(); //结束写入 74 bufferedImage.flush(); //结束buffered 75 ImageIO.write(bufferedImage, "png", new File("E:/img.png")); //将图片写入到指定路径下 76 77 } 78 }
QRCode解析二维码代码如下:
1 import java.awt.image.BufferedImage; 2 import java.io.File; 3 import java.io.IOException; 4 5 import javax.imageio.ImageIO; 6 7 import jp.sourceforge.qrcode.QRCodeDecoder; 8 9 public class ReadQRCode { 10 11 public static void main(String[] args) throws IOException { 12 13 //图片路径 14 File file = new File("E:/img.png"); 15 //读取图片到缓冲区 16 BufferedImage bufferedImage = ImageIO.read(file); 17 //QRCode解码器 18 QRCodeDecoder codeDecoder = new QRCodeDecoder(); 19 20 /** 21 *codeDecoder.decode(new MyQRCodeImage()) 22 *这里需要实现QRCodeImage接口,MyQRCodeImage.java实现接口类 23 */ 24 //通过解析二维码获得信息 25 String result = new String(codeDecoder.decode(new MyQRCodeImage(bufferedImage)), "utf-8"); 26 System.out.println(result); 27 } 28 }
MyQRCodeImage.java类实现QRCodeImage接口
1 import java.awt.image.BufferedImage; 2 3 import jp.sourceforge.qrcode.data.QRCodeImage; 4 5 public class MyQRCodeImage implements QRCodeImage{ 6 7 BufferedImage bufferedImage; 8 9 public MyQRCodeImage(BufferedImage bufferedImage) { 10 this.bufferedImage = bufferedImage; 11 } 12 13 //宽 14 @Override 15 public int getWidth() { 16 return bufferedImage.getWidth(); 17 } 18 19 //高 20 @Override 21 public int getHeight() { 22 return bufferedImage.getHeight(); 23 } 24 25 //颜色 26 @Override 27 public int getPixel(int i, int j) { 28 return bufferedImage.getRGB(i, j); 29 } 30 }
七、注意事项
jar包可放置在lib包下,还要设置此项目的builde path,选中项目,右击,选择Builde Path,点击Configure Builde Path,在libraries下点击Add Jars添加jar文件。