Java如何實現(xiàn)批量打印條形碼
一、項目背景詳細介紹
在倉儲管理、商品追溯、物流配送等場景中,條形碼(Barcode)作為物品唯一標識被廣泛使用。為提高效率,經(jīng)常需要將一批數(shù)據(jù)轉為條形碼并打印在標簽紙或 A4 頁面上,滿足打包掃描、入庫出庫等作業(yè)流程。
傳統(tǒng)做法可能依賴專有打標簽軟件,靈活性差且難以集成到定制化系統(tǒng)。使用 Java 開發(fā)一套 批量生成并打印條形碼 的工具,可以:
靈活集成:嵌入現(xiàn)有倉儲或 ERP 系統(tǒng),直接從數(shù)據(jù)庫或 CSV 導入數(shù)據(jù);
定制標簽:支持調整條形碼大小、分辨率、文字位置;
自動化批量:一鍵批量生成、分頁排版、提交給打印機;
零第三方依賴:僅需開源庫 ZXing 和 Java 自帶打印 API。
本項目將演示如何基于 ZXing 庫生成條形碼位圖,利用 Java 打印服務(PrinterJob)將它們以網(wǎng)格方式批量打印到 A4 標簽紙或標簽紙格式(如 3×10 布局)。
二、項目需求詳細介紹
2.1 功能需求
1.批量數(shù)據(jù)導入
支持從文本文件(CSV)、數(shù)據(jù)庫或內(nèi)存列表讀取多條待編碼內(nèi)容;
2.條形碼生成
- 使用 ZXing 生成 Code128 或 EAN-13 條形碼;
- 支持指定寬度、高度、邊距及是否顯示文本;
3.分頁排版
- 在 A4 紙或標簽紙上按指定行列(如 2 列×5 行)自動排版;
- 支持頁眉頁腳或批次號打??;
4.打印預覽(可選)
彈出打印對話框預覽分頁及打印機設置;
5.提交打印
通過 PrinterJob 接口,支持選擇打印機及打印范圍;
6.錯誤處理與日志
捕獲生成失敗、打印失敗,記錄日志并跳過繼續(xù);
2.2 非功能需求
易用性:一行命令或簡單 GUI 即可完成;
配置化:頁面尺寸、行列數(shù)、條碼樣式通過配置文件管理;
跨平臺:僅依賴 Java SE 與 ZXing,可在 Windows、Linux、macOS 上運行;
可擴展:后續(xù)可支持二維碼(QR Code)等多種格式;
三、相關技術詳細介紹
1.ZXing (com.google.zxing)
- 主流開源條碼/二維碼生成與解析庫;
- 支持多種碼制:Code128, EAN13, QR_CODE 等;
2.Java2D (java.awt.Graphics2D)
在 BufferedImage 上繪制條碼位圖;
3.PrinterJob (java.awt.print)
- 標準打印 API:PrinterJob、PageFormat、Printable;
- 支持頁面設置與打印對話框;
4.配置管理
使用 java.util.Properties 或 Spring @ConfigurationProperties 加載標簽布局;
5.日志框架
SLF4J + Logback 記錄運行狀態(tài);
四、實現(xiàn)思路詳細介紹
1.加載配置與數(shù)據(jù)
- 從 config.properties 讀?。喉撁鎸挾取⒏叨?、行數(shù)、列數(shù)、條形碼尺寸、邊距等;
- 從 CSV 或數(shù)據(jù)庫加載待打印的編碼字符串列表;
2.生成條形碼圖像
- 對每條內(nèi)容調用 ZXing 的 MultiFormatWriter.encode(),生成 BitMatrix;
- 將 BitMatrix 轉換為 BufferedImage,并在底部添加文本標簽(可選);
3.分頁排版
實現(xiàn) Printable 接口:
- 在 print(Graphics g, PageFormat pf, int pageIndex) 中,根據(jù) pageIndex 計算當前頁的數(shù)據(jù)子列表;
- 對每行每列繪制對應條碼圖像,使用 g.drawImage();
- 如有文字批次號或條碼文本,使用 Graphics2D.drawString();
- 返回 PAGE_EXISTS 或 NO_SUCH_PAGE;
4.打印提交
PrinterJob job = PrinterJob.getPrinterJob(); job.setPrintable(printable, pageFormat); if(job.printDialog()) job.print();
5.日志與異常
條碼生成或打印異常時,捕獲并記錄,跳過當前碼或重試;
五、完整實現(xiàn)代碼
import com.google.zxing.*;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.oned.Code128Writer;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.print.*;
import java.io.*;
import java.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BatchBarcodePrinter implements Printable {
private static final Logger logger = LoggerFactory.getLogger(BatchBarcodePrinter.class);
private List<String> codes; // 待打印內(nèi)容
private Properties config; // 布局及條碼配置
private List<BufferedImage> images; // 生成的條碼圖像列表
private int cols, rows; // 每頁列數(shù)和行數(shù)
private int imgWidth, imgHeight; // 條碼圖像尺寸
private int marginX, marginY; // 頁面邊距
private int gapX, gapY; // 圖像間隔
public BatchBarcodePrinter(List<String> codes, Properties cfg) throws Exception {
this.codes = codes;
this.config = cfg;
loadConfig();
generateImages();
}
// 讀取配置
private void loadConfig() {
cols = Integer.parseInt(config.getProperty("page.cols", "2"));
rows = Integer.parseInt(config.getProperty("page.rows", "5"));
imgWidth = Integer.parseInt(config.getProperty("barcode.width", "200"));
imgHeight = Integer.parseInt(config.getProperty("barcode.height", "80"));
marginX = Integer.parseInt(config.getProperty("page.marginX", "50"));
marginY = Integer.parseInt(config.getProperty("page.marginY", "50"));
gapX = Integer.parseInt(config.getProperty("page.gapX", "20"));
gapY = Integer.parseInt(config.getProperty("page.gapY", "30"));
}
// 生成所有條碼圖像
private void generateImages() {
images = new ArrayList<>();
Code128Writer writer = new Code128Writer();
for (String code : codes) {
try {
BitMatrix bm = writer.encode(code, BarcodeFormat.CODE_128, imgWidth, imgHeight);
BufferedImage img = new BufferedImage(imgWidth, imgHeight + 20, BufferedImage.TYPE_INT_RGB);
Graphics2D g = img.createGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, img.getWidth(), img.getHeight());
// 繪制條碼
for (int x = 0; x < imgWidth; x++) {
for (int y = 0; y < imgHeight; y++) {
g.setColor(bm.get(x, y) ? Color.BLACK : Color.WHITE);
g.fillRect(x, y, 1, 1);
}
}
// 繪制文本
g.setColor(Color.BLACK);
g.setFont(new Font("Monospaced", Font.PLAIN, 14));
FontMetrics fm = g.getFontMetrics();
int tx = (imgWidth - fm.stringWidth(code)) / 2;
g.drawString(code, tx, imgHeight + fm.getAscent());
g.dispose();
images.add(img);
} catch (Exception e) {
logger.error("生成條碼失敗: {}", code, e);
}
}
}
@Override
public int print(Graphics graphics, PageFormat pf, int pageIndex) {
int perPage = cols * rows;
int start = pageIndex * perPage;
if (start >= images.size()) return NO_SUCH_PAGE;
Graphics2D g = (Graphics2D) graphics;
g.translate(pf.getImageableX(), pf.getImageableY());
int x0 = marginX, y0 = marginY;
// 繪制本頁條碼
for (int i = 0; i < perPage; i++) {
int idx = start + i;
if (idx >= images.size()) break;
int row = i / cols, col = i % cols;
int x = x0 + col * (imgWidth + gapX);
int y = y0 + row * (imgHeight + gapY + 20);
g.drawImage(images.get(idx), x, y, null);
}
return PAGE_EXISTS;
}
// 啟動打印
public void printAll() throws PrinterException {
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintable(this);
if (job.printDialog()) {
job.print();
}
}
public static void main(String[] args) throws Exception {
// 1. 加載待打印數(shù)據(jù)
List<String> codes = new ArrayList<>();
try (BufferedReader br = new BufferedReader(new FileReader("codes.csv"))) {
String line;
while ((line = br.readLine()) != null) {
if (!line.trim().isEmpty()) codes.add(line.trim());
}
}
// 2. 加載配置
Properties cfg = new Properties();
try (InputStream in = new FileInputStream("config.properties")) {
cfg.load(in);
}
// 3. 批量打印
BatchBarcodePrinter printer = new BatchBarcodePrinter(codes, cfg);
printer.printAll();
}
}六、代碼詳細解讀
1.配置加載
從 config.properties 中讀取:page.cols, page.rows(每頁行列數(shù))、barcode.width, barcode.height(條碼圖像尺寸)、頁邊距與間隔等,便于靈活調整布局。
2.條碼生成
使用 ZXing 的 Code128Writer 生成 BitMatrix,逐像素渲染到 BufferedImage,并在下方繪制文本。
3.實現(xiàn) Printable
print(...) 根據(jù) pageIndex 計算本頁起始索引,并按行列遍歷繪制對應條碼圖像,返回 PAGE_EXISTS 或 NO_SUCH_PAGE 控制分頁。
4.打印提交
PrinterJob 彈出打印對話框,用戶可選擇打印機與份數(shù),調用 print() 發(fā)起。
5.主方法流程
- 從 codes.csv 讀取待打印條碼列表;
- 從 config.properties 加載布局與尺寸;
- 構造 BatchBarcodePrinter 并調用 printAll()。
七、項目詳細總結
本項目展示了如何用 Java + ZXing + PrinterJob 實現(xiàn) 批量打印條形碼:
數(shù)據(jù)靈活:支持從文件或數(shù)據(jù)庫導入任意數(shù)量的編碼字符串;
配置驅動:行列數(shù)、圖像大小、頁邊距等通過外部配置調整;
圖形生成:ZXing 可靠生成高質量 Code128 條碼,并可擴展到 QR Code;
分頁打?。簶藴?Java 打印 API 自動分頁,兼容任意打印機;
零商業(yè)依賴:僅用開源組件即可完成企業(yè)級標簽打印需求。
適合物流、倉儲、制造業(yè)等需要批量生產(chǎn)標簽的場景,也可作為 Java 圖形與打印 API 教學案例。
八、項目常見問題及解答
Q1:條碼圖像模糊或尺寸不符?
A:確認 imgWidth/imgHeight 與實際打印機 DPI 配合,必要時增加分辨率或調整頁面縮放。
Q2:打印出現(xiàn)空白頁?
A:檢查 print() 返回值邏輯,確保當 start >= images.size() 時返回 NO_SUCH_PAGE,否則會多打印空頁。
Q3:條碼下方文字不居中?
A:文本繪制使用 FontMetrics 計算字符串寬度,確保 x = (imgWidth - textWidth)/2。
Q4:需要打印二維碼?
A:將 Code128Writer 換為 QRCodeWriter,并設置 BitMatrix 尺寸,文本可放到旁邊或不顯示。
九、擴展方向與性能優(yōu)化
大批量流式生成:對超萬條數(shù)據(jù),分批生成圖像并實時打印,避免一次性占用大量內(nèi)存;
自定義標簽紙尺寸:支持常見標簽紙(如 4×8 標簽)模板配置,精確匹配打印機紙張;
并發(fā)打?。憾嗑€程調用不同 PrinterJob 實例同時發(fā)送到多臺打印機;
網(wǎng)絡打印集成:支持通過 IPP 協(xié)議或打印服務器推送打印作業(yè);
RTF/Word 導出:在 Word 文檔或 RTF 中嵌入條碼圖像,擴展報表輸出;
GUI 預覽與編輯:用 Swing 或 JavaFX 提供可視化布局工具,讓用戶拖拽調整標簽位置。
到此這篇關于Java如何實現(xiàn)批量打印條形碼的文章就介紹到這了,更多相關Java打印條形碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Spring中@Configuration注解和@Component注解的區(qū)別詳解
這篇文章主要介紹了Spring中@Configuration注解和@Component注解的區(qū)別詳解,@Configuration 和 @Component 到底有何區(qū)別呢?我先通過如下一個案例,在不分析源碼的情況下,小伙伴們先來直觀感受一下這兩個之間的區(qū)別,需要的朋友可以參考下2023-09-09
Java實現(xiàn)文件上傳到服務器本地并通過url訪問的方法步驟
最近項目中使用到了文件上傳到服務器的功能,下面這篇文章主要給大家介紹了關于Java實現(xiàn)文件上傳到服務器本地并通過url訪問的方法步驟,文中通過圖文以及實例代碼介紹的非常詳細,需要的朋友可以參考下2023-04-04
PowerJob的TimingStrategyHandler工作流程源碼解讀
這篇文章主要為大家介紹了PowerJob的TimingStrategyHandler工作流程源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2024-01-01
SpringBoot選擇自有bean優(yōu)先加載實現(xiàn)方法
在一些需求中,可能存在某些場景,比如先加載自己的bean,然后自己的bean做一些DB操作,初始化配置問題,然后后面的bean基于這個配置文件,繼續(xù)做其他的業(yè)務邏輯。因此有了本文的這個題目2023-03-03
Java微信公眾平臺開發(fā)(5) 文本及圖文消息回復的實現(xiàn)
這篇文章主要為大家詳細介紹了Java微信公眾平臺開發(fā)第五步,回文本及圖文消息回復的實現(xiàn)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-04-04

