java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java打印条形码

Java如何实现批量打印条形码

作者:Katie。

这篇文章主要为大家详细介绍了如何基于 ZXing 库生成条形码位图,并利用 Java 打印服务(PrinterJob)将它们以网格方式批量打印到 A4 标签纸或标签纸格式,需要的小伙伴可以参考一下

一、项目背景详细介绍

在仓储管理、商品追溯、物流配送等场景中,条形码(Barcode)作为物品唯一标识被广泛使用。为提高效率,经常需要将一批数据转为条形码并打印在标签纸或 A4 页面上,满足打包扫描、入库出库等作业流程。

传统做法可能依赖专有打标签软件,灵活性差且难以集成到定制化系统。使用 Java 开发一套 批量生成并打印条形码 的工具,可以:

灵活集成:嵌入现有仓储或 ERP 系统,直接从数据库或 CSV 导入数据;

定制标签:支持调整条形码大小、分辨率、文字位置;

自动化批量:一键批量生成、分页排版、提交给打印机;

零第三方依赖:仅需开源库 ZXing 和 Java 自带打印 API。

本项目将演示如何基于 ZXing 库生成条形码位图,利用 Java 打印服务(PrinterJob)将它们以网格方式批量打印到 A4 标签纸或标签纸格式(如 3×10 布局)。

二、项目需求详细介绍

2.1 功能需求

1.批量数据导入

支持从文本文件(CSV)、数据库或内存列表读取多条待编码内容;

2.条形码生成

3.分页排版

4.打印预览(可选)

弹出打印对话框预览分页及打印机设置;

5.提交打印

通过 PrinterJob 接口,支持选择打印机及打印范围;

6.错误处理与日志

捕获生成失败、打印失败,记录日志并跳过继续;

2.2 非功能需求

易用性:一行命令或简单 GUI 即可完成;

配置化:页面尺寸、行列数、条码样式通过配置文件管理;

跨平台:仅依赖 Java SE 与 ZXing,可在 Windows、Linux、macOS 上运行;

可扩展:后续可支持二维码(QR Code)等多种格式;

三、相关技术详细介绍

1.ZXing (com.google.zxing)

2.Java2D (java.awt.Graphics2D)

在 BufferedImage 上绘制条码位图;

3.PrinterJob (java.awt.print)

4.配置管理

使用 java.util.Properties 或 Spring @ConfigurationProperties 加载标签布局;

5.日志框架

SLF4J + Logback 记录运行状态;

四、实现思路详细介绍

1.加载配置与数据

2.生成条形码图像

3.分页排版

实现 Printable 接口:

4.打印提交

PrinterJob job = PrinterJob.getPrinterJob(); job.setPrintable(printable, pageFormat); if(job.printDialog()) job.print();

5.日志与异常

条码生成或打印异常时,捕获并记录,跳过当前码或重试;

五、完整实现代码

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;         // 待打印内容
    private Properties config;          // 布局及条码配置
    private List<BufferedImage> images; // 生成的条码图像列表
    private int cols, rows;             // 每页列数和行数
    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. 加载待打印数据
        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(每页行列数)、barcode.width, barcode.height(条码图像尺寸)、页边距与间隔等,便于灵活调整布局。

2.条码生成

使用 ZXing 的 Code128Writer 生成 BitMatrix,逐像素渲染到 BufferedImage,并在下方绘制文本。

3.实现 Printable

print(...) 根据 pageIndex 计算本页起始索引,并按行列遍历绘制对应条码图像,返回 PAGE_EXISTS 或 NO_SUCH_PAGE 控制分页。

4.打印提交

PrinterJob 弹出打印对话框,用户可选择打印机与份数,调用 print() 发起。

5.主方法流程

七、项目详细总结

本项目展示了如何用 Java + ZXing + PrinterJob 实现 批量打印条形码:

数据灵活:支持从文件或数据库导入任意数量的编码字符串;

配置驱动:行列数、图像大小、页边距等通过外部配置调整;

圖形生成:ZXing 可靠生成高质量 Code128 条码,并可扩展到 QR Code;

分页打印:标准 Java 打印 API 自动分页,兼容任意打印机;

零商业依赖:仅用开源组件即可完成企业级标签打印需求。

适合物流、仓储、制造业等需要批量生产标签的场景,也可作为 Java 图形与打印 API 教学案例。

八、项目常见问题及解答

Q1:条码图像模糊或尺寸不符?

A:确认 imgWidth/imgHeight 与实际打印机 DPI 配合,必要时增加分辨率或调整页面缩放。

Q2:打印出现空白页?

A:检查 print() 返回值逻辑,确保当 start >= images.size() 时返回 NO_SUCH_PAGE,否则会多打印空页。

Q3:条码下方文字不居中?

A:文本绘制使用 FontMetrics 计算字符串宽度,确保 x = (imgWidth - textWidth)/2。

Q4:需要打印二维码?

A:将 Code128Writer 换为 QRCodeWriter,并设置 BitMatrix 尺寸,文本可放到旁边或不显示。

九、扩展方向与性能优化

大批量流式生成:对超万条数据,分批生成图像并实时打印,避免一次性占用大量内存;

自定义标签纸尺寸:支持常见标签纸(如 4×8 标签)模板配置,精确匹配打印机纸张;

并发打印:多线程调用不同 PrinterJob 实例同时发送到多台打印机;

网络打印集成:支持通过 IPP 协议或打印服务器推送打印作业;

RTF/Word 导出:在 Word 文档或 RTF 中嵌入条码图像,扩展报表输出;

GUI 预览与编辑:用 Swing 或 JavaFX 提供可视化布局工具,让用户拖拽调整标签位置。

到此这篇关于Java如何实现批量打印条形码的文章就介绍到这了,更多相关Java打印条形码内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文