技術棧
- QRCode.jar:日本スウェテーク開發的經典 QR Code 庫(SourceForge.jp 託管)
- 純 Java 實現,無原生依賴,輕量級(~100KB)
Maven 依賴(手動安裝到本地倉庫)
mvn install:install-file -Dfile=QRCode.jar -DgroupId=jp.sourceforge.qrcode -DartifactId=qrcode -Dversion=1.0 -Dpackaging=jar
核心類:TwoDimensionCode
package qrcode;
import com.swetake.util.Qrcode;
import jp.sourceforge.qrcode.QRCodeDecoder;
import jp.sourceforge.qrcode.exception.DecodingFailedException;
import jp.sourceforge.qrcode.data.QRCodeImage;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
public class TwoDimensionCode {
/** 生成二維碼到文件 */
public void encoderQRCode(String content, String imgPath) {
encoderQRCode(content, imgPath, "png", 7);
}
public void encoderQRCode(String content, OutputStream output) {
encoderQRCode(content, output, "png", 7);
}
public void encoderQRCode(String content, String imgPath, String imgType, int size) {
try {
BufferedImage bufImg = qRCodeCommon(content, imgType, size);
ImageIO.write(bufImg, imgType, new File(imgPath));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void encoderQRCode(String content, OutputStream output, String imgType, int size) {
try {
BufferedImage bufImg = qRCodeCommon(content, imgType, size);
ImageIO.write(bufImg, imgType, output);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/** 核心繪製邏輯 */
private BufferedImage qRCodeCommon(String content, String imgType, int size) {
Qrcode handler = new Qrcode();
handler.setQrcodeErrorCorrect('M'); // M級 15% 容錯
handler.setQrcodeEncodeMode('B'); // Byte 模式
handler.setQrcodeVersion(size); // 1-40 版本
byte[] contentBytes = content.getBytes(StandardCharsets.UTF_8);
int imgSize = 67 + 12 * (size - 1); // 計算圖片邊長
BufferedImage bufImg = new BufferedImage(imgSize, imgSize, BufferedImage.TYPE_INT_RGB);
Graphics2D gs = bufImg.createGraphics();
gs.setBackground(Color.WHITE);
gs.clearRect(0, 0, imgSize, imgSize);
gs.setColor(Color.BLACK);
int pixoff = 2; // 偏移量,關鍵參數,影響解析成功率
if (contentBytes.length > 0 && contentBytes.length < 800) {
boolean[][] codeOut = handler.calQrcode(contentBytes);
for (int i = 0; i < codeOut.length; i++) {
for (int j = 0; j < codeOut.length; j++) {
if (codeOut[j][i]) {
gs.fillRect(j * 3 + pixoff, i * 3 + pixoff, 3, 3);
}
}
}
} else {
throw new IllegalArgumentException("內容長度需在 1-800 字節之間");
}
gs.dispose();
bufImg.flush();
return bufImg;
}
/** 解析二維碼文件 */
public String decoderQRCode(String imgPath) {
try {
BufferedImage bufImg = ImageIO.read(new File(imgPath));
QRCodeDecoder decoder = new QRCodeDecoder();
return new String(decoder.decode(new TwoDimensionCodeImage(bufImg)), "UTF-8");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public String decoderQRCode(InputStream input) {
try {
BufferedImage bufImg = ImageIO.read(input);
QRCodeDecoder decoder = new QRCodeDecoder();
return new String(decoder.decode(new TwoDimensionCodeImage(bufImg)), "UTF-8");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/** 測試入口 */
public static void main(String[] args) {
String path = "G:/QRCode.png";
String content = "Hello QRCode!\nBlog: https://example.com\nEmail: test@example.com";
TwoDimensionCode handler = new TwoDimensionCode();
handler.encoderQRCode(content, path, "png", 7);
System.out.println("生成成功");
String decoded = handler.decoderQRCode(path);
System.out.println("解析結果:\n" + decoded);
}
}
輔助類:TwoDimensionCodeImage
package qrcode;
import jp.sourceforge.qrcode.data.QRCodeImage;
import java.awt.image.BufferedImage;
public class TwoDimensionCodeImage implements QRCodeImage {
private final BufferedImage bufImg;
public TwoDimensionCodeImage(BufferedImage bufImg) {
this.bufImg = bufImg;
}
@Override public int getWidth() { return bufImg.getWidth(); }
@Override public int getHeight() { return bufImg.getHeight(); }
@Override public int getPixel(int x, int y) { return bufImg.getRGB(x, y); }
}
關鍵參數說明
| 參數 | 範圍/選項 | 影響 |
| ErrorCorrect | L(7%) M(15%) Q(25%) H(30%) | 容錯越高,可存內容越少,但抗污損能力越強 |
| EncodeMode | N(數字) A(字母數字) B(8-bit字節) K(日文) | B 模式通用性最強,支持中文 UTF-8 |
| Version | 1-40 | 版本越大,矩陣越大,容量越高 |
| pixoff | 建議 2 | 模塊繪製偏移,太小邊緣模糊,太大超出畫布 |
| 模塊像素 | 固定 3x3 | 每個邏輯模塊對應 3x3 物理像素,影響最終圖片尺寸 |
優缺點對比
| 維度 | QRCode.jar | ZXing |
| Jar 體積 | ~100KB | core ~500KB + javase ~300KB |
| API 設計 | 簡單直接 | 功能豐富,支持多格式、多平台 |
| Logo 嵌入 | 需自行繪製 | 社區有成熟封裝 |
| 維護狀態 | 多年未更新 | 活躍維護,支持最新 JDK |
| 適用場景 | 輕量、舊項目、無 Logo 需求 | 新項目、多格式、需 Logo/樣式定制 |
QRCode.jar 適合快速集成、極簡依賴、無花哨需求的老項目;新項目首選 ZXing,生態更完善。