1. 二维码基础
1.1概念
二维码:某种特定几何图形按一定规律在平面上分布的条,空相间的图形来记录数据符号的信息。
1.2分类
线性堆叠式二维码;
矩阵式二维码;
邮政码。
2.国家标准GB
3.QR Code类二维码
3.1ZXing工具生成/解析
ZXing: https://github.com/zxing 需要引入zxing-3.4.0.jar
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.4.0</version>
</dependency>
package com.wdy.utils;
import com.google.common.collect.Maps; import com.google.zxing.*; import com.google.zxing.client.j2se.BufferedImageLuminanceSource; import com.google.zxing.client.j2se.MatrixToImageWriter; import com.google.zxing.common.BitMatrix; import com.google.zxing.common.HybridBinarizer; import com.google.zxing.datamatrix.encoder.ErrorCorrection; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import org.apache.http.HttpResponse;
import javax.imageio.ImageIO; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.awt.image.BufferedImage; import java.io.*; import java.io.Writer; import java.nio.file.Path; import java.util.HashMap; import java.util.Map;
/** * Created by wangdy on 2017/7/20. */ public class ZXingUtil {
public static void main(String[] args) { // createZXingQRCodeToFile(300, 300, "png", "I am wangdy,哈哈", "qrcode.png"); Map<String, Object> stringObjectMap = readZXingQRCodeToFile("qrcode.png"); System.out.println("" + stringObjectMap.get("result"));
}
/** * 使用ZXing工具生成qrcode二维码---到文件 * * @param width 宽度 * @param height 高度 * @param format 扩展名 eg png * @param content 文字内容 * @param filePath 输出文件路径 * @date:2017/7/20 23:29 */ public static void createZXingQRCodeToFile(int width, int height, String format, String content, String filePath) { HashMap hints = new HashMap(); //设置文字编码 hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); //设置容错等级,常用M hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M); //设置二维码四周空白,默认5 hints.put(EncodeHintType.MARGIN, 2); try { BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints); Path path = new File(filePath).toPath(); MatrixToImageWriter.writeToPath(bitMatrix, format, path); } catch (Exception e) { e.printStackTrace(); } }
/** * 使用ZXing工具解析二维码 * * @param filePath 文件路径 * @date:2017/7/20 23:29 * @return Map:<"result",value>,<"textResult",value>,<"barcodeFormat",value> */ public static Map<String, Object> readZXingQRCodeToFile(String filePath) { Map<String, Object> resultMap = Maps.newHashMap(); MultiFormatReader multiFormatReader = new MultiFormatReader(); File file = new File(filePath); try { BufferedImage bufferedImage = ImageIO.read(file); BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(bufferedImage))); HashMap hints = new HashMap(); //设置文字编码 hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); Result result = multiFormatReader.decode(binaryBitmap, hints);
System.out.println("解析结果: " + result.toString()); System.out.println("解析文本内容:" + result.getText()); System.out.println("二维码类型:" + result.getBarcodeFormat()); /*解析结果: I am wangdy,哈哈 解析文本内容:I am wangdy,哈哈 二维码类型:QR_CODE*/
resultMap.put("result", result.toString()); resultMap.put("textResult", result.getText()); resultMap.put("barcodeFormat", result.getBarcodeFormat()); } catch (Exception e) { e.printStackTrace(); } return resultMap; } |
3.2QECode工具生成/解析
生成二维码jar:http://www.swetake.com/qrcode/
解析二维码jar:https://zh.osdn.net/projects/qrcode/
1)将下载下来的jar重命名后,安装到本地maven仓库中: 2)引入到工程 3)代码: package com.wdy.utils;
import com.swetake.util.Qrcode;
import jp.sourceforge.qrcode.QRCodeDecoder;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
/**
* 使用QRCode工具生成解析二维码
* Created by wangdy on 2017/7/21.
*/
public class QRCodeUtil {
/**
* 使用QRCode工具生成 二维码
*
* @param qrcodeVersion 版本号 一般用7
* @param content 填充文字
* @param format 扩展名 如png
* @param filePath 生成的文件路径
* @return
* @date:2017/7/21 10:10
*/
public static void createQRCByQRCode(int qrcodeVersion, String content, String format, String filePath) {
Qrcode qrcode = new Qrcode();
qrcode.setQrcodeErrorCorrect('M');
//N代表数字,A代表字母,B代表其他字符,通常B
qrcode.setQrcodeEncodeMode('B');
qrcode.setQrcodeVersion(qrcodeVersion);//版本号
int width = 67 + 12 * (qrcodeVersion - 1);//固定公式
int height = 67 + 12 * (qrcodeVersion - 1);
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
Graphics2D graphics2D = bufferedImage.createGraphics();
graphics2D.setBackground(Color.WHITE);
graphics2D.setColor(Color.BLACK);
graphics2D.clearRect(0, 0, width, height);
int pixoff = 2;//偏移量,绘图使用
byte[] bytes = new byte[0];
try {
bytes = content.getBytes("utf-8");//中文支持
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if (bytes.length > 0 && bytes.length < 120) {
boolean[][] s = qrcode.calQrcode(bytes);
for (int i = 0; i < s.length; i++) {
for (int j = 0; j < s.length; j++) {
if (s[j][i]) {
graphics2D.fillRect(j * 3 + pixoff, i * 3 + pixoff, 3, 3);
}
}
}
graphics2D.dispose();
bufferedImage.flush();
try {
File file = new File(filePath);
boolean write = ImageIO.write(bufferedImage, format, file);
if (write) {
System.out.println("生成二维码成功:位置" + file.getAbsolutePath());
//生成二维码成功:位置E:\mycode\jdbcTempDemo\qrcodecreate.png
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 使用QRCode工具生成 二维码
*
* @param filePath 生成的文件路径
* @return
* @date:2017/7/21 10:10
*/
public static String readQRCByQRCode(String filePath) {
File file = new File(filePath);
String result = "";
try {
BufferedImage bufferedImage = ImageIO.read(file);
QRCodeDecoder qrCodeDecoder = new QRCodeDecoder();
// byte[] decode = qrCodeDecoder.decode(new MyQRCodeImage(bufferedImage));
result = new String(qrCodeDecoder.decode(new MyQRCodeImage(bufferedImage)), "utf-8");
System.out.println("解析结果为:" + result);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public static void main(String[] args) {
// createQRCByQRCode(7, "I am your father,哦也!", "png", "qrcodecreate.png");
String result = readQRCByQRCode("123.png");
System.out.println("" + result);
}
} |
3.3jquery-qrcode生成二维码
https://github.com/jeromeetienne/jquery-qrcode
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<%--注意顺序--%>
<script type="text/javascript" src="<%=request.getContextPath() %>/js/jquery.min.js"></script>
<script type="text/javascript" src="<%=request.getContextPath() %>/js/jquery.qrcode.min.js"></script>
</head>
<body>
生成的二维码如下: <%--注意顺序--%> <div id="qrcode"></div><script type="text/javascript"> jQuery('#qrcode').qrcode({width: 120, height: 120, text: utf16to8("this is content中12文")}); //支持中文方法
function utf16to8(str) {
var out, i, len, c;
out = "";
len = str.length;
for (i = 0; i < len; i++) {
c = str.charCodeAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) {
out += str.charAt(i);
} else if (c > 0x07FF) {
out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
} else {
out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
}
}
return out;
}
</script>
</body>
</html> 特别注意问题:jquery-qrcode生成的二维码用微信/支付宝可以正常扫描,用ZxingUtil工具也可以解析,但用QRCode.jar无法正常解析,错误如下/还有一种可能是解析出的是乱码。 jp.sourceforge.qrcode.exception.DecodingFailedException: Give up decoding at jp.sourceforge.qrcode.QRCodeDecoder.decode(QRCodeDecoder.java:88) at com.wdy.utils.QRCodeUtil.readQRCByQRCode(QRCodeUtil.java:90) at com.wdy.utils.QRCodeUtil.main(QRCodeUtil.java:101) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:483) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144) |