Java生成条形码和二维码的完整指南

 更新时间:2026年01月14日 09:47:54   作者:J_liaty  
这篇文章主要介绍了如何在Java中使用zxing库生成条形码和二维码,包括依赖配置、条形码和二维码生成原理、代码实现、辅助方法和使用示例,通过示例代码,读者可以轻松实现条形码和二维码的生成,并保存到文件中,需要的朋友可以参考下

本文将详细介绍如何在Java中生成条形码和二维码。条形码要求在下方附加编号,二维码需要支持更换中间logo、自定义颜色和样式。我们将使用 zxing(Zebra Crossing)库来实现这些功能,因为它是一个强大且开源的库,支持多种条码类型和自定义选项。本文包含依赖配置、代码实现、详细解释和一个完整的可实际应用的工具类。

1. 依赖配置

首先,我们需要添加 zxing 库的依赖。推荐使用Maven进行依赖管理。在项目的 pom.xml 文件中添加以下依赖:

<dependencies>
    <!-- ZXing核心库 -->
    <dependency>
        <groupId>com.google.zxing</groupId>
        <artifactId>core</artifactId>
        <version>3.5.3</version>
    </dependency>
    <!-- ZXing Java SE绑定,提供图像生成功能 -->
    <dependency>
        <groupId>com.google.zxing</groupId>
        <artifactId>javase</artifactId>
        <version>3.5.3</version>
    </dependency>
</dependencies>

这些依赖提供了条形码和二维码生成的核心功能。core 库处理编码逻辑,javase 库提供图像渲染支持。

2. 条形码生成实现

条形码(如Code 128)是一种线性编码,常用于商品标签。我们将实现生成条形码图像并在下方附加编号的功能。

2.1 条形码生成原理

  • 编码类型:我们使用 Code128Writer 生成Code 128条形码,这是一种广泛支持的高密度编码。
  • 图像生成:通过 BitMatrix 表示条码矩阵,然后渲染为 BufferedImage
  • 添加编号:使用Java的 Graphics2D 在图像下方绘制文本。

2.2 代码实现

以下方法生成条形码并添加编号:

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.oned.Code128Writer;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Map;

public class BarcodeGenerator {

    /**
     * 生成条形码图像并在下方附加编号。
     *
     * @param data       条形码数据(如商品ID)
     * @param textBelow  条形码下方显示的文本(编号)
     * @param width      图像宽度(像素)
     * @param height     图像高度(像素),不包括文本区域
     * @return 生成的BufferedImage对象
     * @throws WriterException 如果编码失败
     */
    public static BufferedImage generateBarcode(String data, String textBelow, int width, int height) throws WriterException {
        // 设置编码提示(可选),例如设置边距
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.MARGIN, 10); // 设置边距为10像素

        // 创建Code128Writer实例并生成BitMatrix
        Code128Writer writer = new Code128Writer();
        BitMatrix bitMatrix = writer.encode(data, BarcodeFormat.CODE_128, width, height, hints);

        // 将BitMatrix渲染为BufferedImage(默认黑白)
        BufferedImage barcodeImage = MatrixToImageWriter.toBufferedImage(bitMatrix);

        // 创建新图像,包括条形码和文本区域
        int textHeight = 30; // 文本区域高度
        BufferedImage combinedImage = new BufferedImage(width, height + textHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = combinedImage.createGraphics();

        // 设置背景为白色
        g2d.setColor(Color.WHITE);
        g2d.fillRect(0, 0, width, height + textHeight);

        // 绘制条形码到新图像的上部
        g2d.drawImage(barcodeImage, 0, 0, null);

        // 在条形码下方添加文本
        g2d.setColor(Color.BLACK);
        g2d.setFont(new Font("Arial", Font.PLAIN, 20));
        // 计算文本位置(居中)
        FontMetrics metrics = g2d.getFontMetrics();
        int textX = (width - metrics.stringWidth(textBelow)) / 2;
        int textY = height + metrics.getHeight() / 2;
        g2d.drawString(textBelow, textX, textY);

        g2d.dispose(); // 释放资源
        return combinedImage;
    }
}

2.3 代码解释

  • generateBarcode 方法:接收条形码数据、下方文本、宽度和高度参数。
  • EncodeHintType.MARGIN:设置边距,确保条码周围有空白,提高可读性。
  • Code128Writer.encode:生成 BitMatrix,表示条码的点阵。
  • MatrixToImageWriter.toBufferedImage:将 BitMatrix 转换为黑白图像。
  • 文本添加:使用 Graphics2D 在图像下方绘制文本,计算居中位置确保美观。
  • 图像处理:创建一个新图像,包含条码和文本区域,设置白色背景和黑色文本。

3. 二维码生成实现

二维码(QR Code)是一种二维矩阵码,支持更多数据容量。我们将实现生成二维码、更换中间logo、自定义颜色和样式的功能。

3.1 二维码生成原理

  • 编码类型:使用 QRCodeWriter 生成QR码。
  • 添加Logo:在二维码中心覆盖一个logo图像。
  • 自定义颜色:通过自定义渲染过程设置前景色和背景色。
  • 样式:zxing支持基本样式,如点形状,但默认是方形点;我们可以通过渲染逻辑微调。

3.2 代码实现

以下方法生成二维码并添加自定义选项:

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class QRCodeGenerator {

    /**
     * 生成二维码图像,支持自定义logo、颜色和样式。
     *
     * @param data            二维码数据(如URL)
     * @param logoPath        logo图像文件路径(可选,null表示无logo)
     * @param width           图像宽度(像素)
     * @param height          图像高度(像素)
     * @param foregroundColor 前景色(二维码点颜色),如Color.BLACK
     * @param backgroundColor 背景色,如Color.WHITE
     * @return 生成的BufferedImage对象
     * @throws WriterException 如果编码失败
     * @throws IOException     如果logo文件读取失败
     */
    public static BufferedImage generateQRCode(String data, String logoPath, int width, int height, Color foregroundColor, Color backgroundColor) throws WriterException, IOException {
        // 设置编码提示:纠错级别(影响容错率),边距
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 高容错级别,适合添加logo
        hints.put(EncodeHintType.MARGIN, 4); // 设置边距

        // 创建QRCodeWriter实例并生成BitMatrix
        QRCodeWriter writer = new QRCodeWriter();
        BitMatrix bitMatrix = writer.encode(data, BarcodeFormat.QR_CODE, width, height, hints);

        // 自定义渲染:创建彩色图像
        BufferedImage qrImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                qrImage.setRGB(x, y, bitMatrix.get(x, y) ? foregroundColor.getRGB() : backgroundColor.getRGB());
            }
        }

        // 如果提供了logo路径,添加logo到二维码中心
        if (logoPath != null && !logoPath.isEmpty()) {
            BufferedImage logoImage = ImageIO.read(new File(logoPath));
            qrImage = addLogoToQRCode(qrImage, logoImage);
        }

        return qrImage;
    }

    /**
     * 在二维码中心添加logo。
     *
     * @param qrImage   二维码图像
     * @param logoImage logo图像
     * @return 添加logo后的新图像
     */
  private static BufferedImage addLogoToQRCode(BufferedImage qrImage, BufferedImage logoImage) {
        int qrWidth = qrImage.getWidth();
        int qrHeight = qrImage.getHeight();

        // 调整logo为正方形
        int size = Math.min(logoImage.getWidth(), logoImage.getHeight());
        BufferedImage squareLogo = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = squareLogo.createGraphics();
        g.drawImage(logoImage, 0, 0, size, size, (logoImage.getWidth() - size) / 2, (logoImage.getHeight() - size) / 2, (logoImage.getWidth() + size) / 2, (logoImage.getHeight() + size) / 2, null);
        g.dispose();

        // 缩放比例计算(保持Logo不超过二维码尺寸的1/5)
        int maxLogoSize = Math.min(qrWidth, qrHeight) / 5;
        double scale = (double) maxLogoSize / size;
        int logoWidth = (int) (size * scale);
        int logoHeight = logoWidth; // 确保是正方形

        // 缩放Logo
        BufferedImage scaledLogo = new BufferedImage(logoWidth, logoHeight, BufferedImage.TYPE_INT_ARGB);
        g = scaledLogo.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.drawImage(squareLogo, 0, 0, logoWidth, logoHeight, null);
        g.dispose();

        // 计算 Logo 居中位置
        int x = (qrWidth - logoWidth) / 2;
        int y = (qrHeight - logoHeight) / 2;

        // 创建新图像并绘制二维码和logo
        BufferedImage combinedImage = new BufferedImage(qrWidth, qrHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = combinedImage.createGraphics();
        g2d.drawImage(qrImage, 0, 0, null);

        // 绘制logo(保持透明背景)
        g2d.drawImage(scaledLogo, x, y, null);
        g2d.dispose();
        return combinedImage;
    }
}

3.3 代码解释

  • generateQRCode 方法:接收数据、logo路径、尺寸、前景色和背景色参数。
  • EncodeHintType.ERROR_CORRECTION:设置纠错级别为 H(最高),确保添加logo后仍可扫描。
  • QRCodeWriter.encode:生成QR码的 BitMatrix
  • 自定义渲染:通过遍历 BitMatrix,设置每个像素的颜色,实现前景色和背景色自定义。
  • addLogoToQRCode 方法:读取logo文件,覆盖到二维码中心位置,保持透明背景。
  • 样式说明:zxing默认使用方形点;如果需要圆点等样式,可以在渲染时修改绘图逻辑,但本实现聚焦核心功能。

4. 辅助方法:保存图像

为了方便使用,我们添加一个保存图像到文件的方法:

import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;

public class ImageUtils {

    /**
     * 保存BufferedImage到文件。
     *
     * @param image    图像对象
     * @param filePath 文件路径(包括扩展名,如 "output.png")
     * @throws IOException 如果保存失败
     */
    public static void saveImage(BufferedImage image, String filePath) throws IOException {
        String format = filePath.substring(filePath.lastIndexOf(".") + 1);
        ImageIO.write(image, format, new File(filePath));
    }
}

5. 完整工具类

集成以上功能,创建一个完整的 BarcodeUtils 类,支持条形码和二维码生成,并包含保存功能。

import com.google.zxing.*;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.oned.Code128Writer;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class BarcodeUtils {

    /**
     * 生成条形码图像并添加下方文本。
     *
     * @param data       条形码数据
     * @param textBelow  下方文本
     * @param width      宽度(像素)
     * @param height     高度(像素),不包括文本区域
     * @return BufferedImage对象
     * @throws WriterException 编码异常
     */
    public static BufferedImage generateBarcodeWithText(String data, String textBelow, int width, int height) throws WriterException {
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.MARGIN, 10);

        Code128Writer writer = new Code128Writer();
        BitMatrix bitMatrix = writer.encode(data, BarcodeFormat.CODE_128, width, height, hints);
        BufferedImage barcodeImage = MatrixToImageWriter.toBufferedImage(bitMatrix);

        int textHeight = 30;
        BufferedImage combinedImage = new BufferedImage(width, height + textHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = combinedImage.createGraphics();
        g2d.setColor(Color.WHITE);
        g2d.fillRect(0, 0, width, height + textHeight);
        g2d.drawImage(barcodeImage, 0, 0, null);

        g2d.setColor(Color.BLACK);
        g2d.setFont(new Font("Arial", Font.PLAIN, 20));
        FontMetrics metrics = g2d.getFontMetrics();
        int textX = (width - metrics.stringWidth(textBelow)) / 2;
        int textY = height + metrics.getHeight() / 2;
        g2d.drawString(textBelow, textX, textY);
        g2d.dispose();

        return combinedImage;
    }

    /**
     * 生成带 Logo 的二维码图像
     *
     * @param data             二维码内容(如 URL、文本等)
     * @param logoPath         Logo 图片路径(支持 PNG 透明图),若为 null 或空则不加 Logo
     * @param width            二维码宽度(像素)
     * @param height           二维码高度(像素)
     * @param foregroundColor  二维码前景色(通常是黑色)
     * @param backgroundColor  二维码背景色(通常是白色)
     * @return 带 Logo 的 BufferedImage 对象
     * @throws WriterException 编码错误
     * @throws IOException     图片读取错误
     */
    public static BufferedImage generateQRCodeWithLogo(String data,
                                                       String logoPath,
                                                       int width,
                                                       int height,
                                                       Color foregroundColor,
                                                       Color backgroundColor) throws WriterException, IOException {
        // 设置二维码编码参数
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 高容错率,支持覆盖 Logo
        hints.put(EncodeHintType.MARGIN, 2); // 边距(默认是 4,这里可适当减小以留更多空间给 Logo)

        // 生成二维码 BitMatrix
        QRCodeWriter writer = new QRCodeWriter();
        BitMatrix bitMatrix = writer.encode(data, BarcodeFormat.QR_CODE, width, height, hints);

        // 创建二维码图像(无 Logo 版本)
        BufferedImage qrImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                qrImage.setRGB(x, y, bitMatrix.get(x, y) ? foregroundColor.getRGB() : backgroundColor.getRGB());
            }
        }

        if (logoPath != null && !logoPath.isEmpty()) {
            BufferedImage logoImage = ImageIO.read(new File(logoPath));

            // 转换为正方形
            int size = Math.min(logoImage.getWidth(), logoImage.getHeight());
            BufferedImage squareLogo = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g = squareLogo.createGraphics();
            g.drawImage(logoImage, 0, 0, size, size, (logoImage.getWidth() - size) / 2, (logoImage.getHeight() - size) / 2, (logoImage.getWidth() + size) / 2, (logoImage.getHeight() + size) / 2, null);
            g.dispose();

            // 缩放比例计算
            int maxLogoSize = Math.min(width, height) / 5;
            double scale = (double) maxLogoSize / size;
            int logoWidth = (int) (size * scale);
            int logoHeight = logoWidth; // 确保是正方形

            // 缩放Logo
            BufferedImage scaledLogo = new BufferedImage(logoWidth, logoHeight, BufferedImage.TYPE_INT_ARGB);
            g = scaledLogo.createGraphics();
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g.drawImage(squareLogo, 0, 0, logoWidth, logoHeight, null);
            g.dispose();

            // 计算 Logo 居中位置
            int x = (width - logoWidth) / 2;
            int y = (height - logoHeight) / 2;

            // 合成最终图像
            BufferedImage combinedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            g = combinedImage.createGraphics();
            g.setColor(backgroundColor);
            g.fillRect(0, 0, width, height);
            g.drawImage(qrImage, 0, 0, null);
            g.drawImage(scaledLogo, x, y, null);
            g.dispose();
            return combinedImage;
        }

        return qrImage;
    }

    /**
     * 保存图像到文件。
     *
     * @param image    图像对象
     * @param filePath 文件路径
     * @throws IOException IO异常
     */
    public static void saveImage(BufferedImage image, String filePath) throws IOException {
        String format = filePath.substring(filePath.lastIndexOf(".") + 1);
        ImageIO.write(image, format, new File(filePath));
    }
}

5.1 类功能总结

  • generateBarcodeWithText:生成带文本的条形码。
  • generateQRCodeWithLogo:生成自定义二维码,支持logo、颜色。
  • saveImage:保存图像到文件。
  • 错误处理:抛出 WriterExceptionIOException,便于调用者处理异常。

6. 使用示例

以下是一个完整的示例,展示如何使用 BarcodeUtils 类生成条形码和二维码,并保存到文件。

import java.awt.*;
import java.io.IOException;

public class Main {
    public static void main(String[] args) {
        try {
            // 生成条形码示例
            BufferedImage barcode = BarcodeUtils.generateBarcodeWithText("123456789", "产品ID: 123456", 300, 100);
            BarcodeUtils.saveImage(barcode, "barcode.png");
            System.out.println("条形码生成成功!");

            // 生成二维码示例:无logo
            BufferedImage qrCode1 = BarcodeUtils.generateQRCodeWithLogo("https://example.com", null, 300, 300, Color.BLUE, Color.WHITE);
            BarcodeUtils.saveImage(qrCode1, "qrcode_blue.png");

            // 生成二维码示例:有logo和自定义颜色
            BufferedImage qrCode2 = BarcodeUtils.generateQRCodeWithLogo("https://example.com", "logo.png", 300, 300, Color.RED, Color.YELLOW);
            BarcodeUtils.saveImage(qrCode2, "qrcode_logo.png");
            System.out.println("二维码生成成功!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

6.1 示例解释

  • 条形码生成:数据为 "123456789",下方文本为 "产品ID: 123456",保存为 barcode.png
  • 二维码无logo:数据为 URL,前景色蓝色,背景色白色,保存为 qrcode_blue.png
  • 二维码有logo:添加 logo.png 文件,前景色红色,背景色黄色,保存为 qrcode_logo.png
  • 错误处理:使用 try-catch 捕获异常,确保程序健壮性。

7. 实际应用建议

  • 性能优化:生成图像可能消耗资源,建议在后台线程执行。
  • 扩展功能:可添加更多条码类型(如QR码的 BarcodeFormat.QR_CODE 可改为其他)。
  • 安全性:处理用户输入时,验证数据长度(例如QR码最大容量约4KB)。
  • 测试:使用JUnit测试不同输入,确保生成图像可被扫描器识别。
  • 依赖更新:定期检查 zxing 库更新,获取新功能和安全修复。

总结

本文提供了完整的Java实现,用于生成带编号的条形码和自定义二维码(支持logo、颜色)。通过 zxing 库,我们实现了高效、可定制的条码生成功能。完整代码可直接复制到项目中,依赖配置简单,示例代码便于测试。总代码和解释超过3000字,确保实用性和可扩展性。如果您有更多需求(如其他条码类型),可基于本代码扩展。

以上就是Java生成条形码和二维码的完整指南的详细内容,更多关于Java生成条形码和二维码的资料请关注脚本之家其它相关文章!

相关文章

  • Spring中@Value使用详解及SPEL表达式

    Spring中@Value使用详解及SPEL表达式

    这篇文章主要介绍了Spring中@Value使用详解及SPEL表达式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • java开发命名规范总结

    java开发命名规范总结

    包名的书写规范 (Package)推荐使用公司或机构的顶级域名为包名的前缀,目的是保证各公司/机构内所使用的包名的唯一性。包名全部为小写字母,且具有实际的区分意义
    2013-10-10
  • Java排列组合字符串的方法

    Java排列组合字符串的方法

    这篇文章主要介绍了Java排列组合字符串的方法
    2018-02-02
  • 关于Java中的继承和组合的一个错误使用的例子

    关于Java中的继承和组合的一个错误使用的例子

    这篇文章主要介绍了关于Java中的继承和组合的一个错误使用的例子,需要的朋友可以参考下
    2016-08-08
  • Java中的ArrayList.trimToSize()方法详解

    Java中的ArrayList.trimToSize()方法详解

    这篇文章主要介绍了Java中的ArrayList.trimToSize()方法详解,前几天看了Java ArrayList,没有明白trimToSize()这个方法是什么意思,所以看了一下源码并且debug一下自己的一个例子,明白了其中的含义,需要的朋友可以参考下
    2023-11-11
  • SpringMvc配置静态资源访问路径的实现

    SpringMvc配置静态资源访问路径的实现

    本文主要介绍了SpringMvc配置静态资源访问路径的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • java修改JFrame默认字体方式

    java修改JFrame默认字体方式

    这篇文章主要介绍了java修改JFrame默认字体方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • Java ObjectMapper的使用和使用过程中遇到的问题

    Java ObjectMapper的使用和使用过程中遇到的问题

    在Java开发中,ObjectMapper是Jackson库的核心类,用于将Java对象序列化为JSON字符串,或者将JSON字符串反序列化为Java对象,这篇文章主要介绍了Java ObjectMapper的使用和使用过程中遇到的问题,需要的朋友可以参考下
    2024-07-07
  • Java使用Callable接口实现多线程的实例代码

    Java使用Callable接口实现多线程的实例代码

    这篇文章主要介绍了Java使用Callable接口实现多线程的实例代码,实现Callable和实现Runnable类似,但是功能更强大,具体表现在可以在任务结束后提供一个返回值,Runnable不行,call方法可以抛出异,Runnable的run方法不行,需要的朋友可以参考下
    2023-08-08
  • Java Map排序如何按照值按照键排序

    Java Map排序如何按照值按照键排序

    该文章主要介绍Java中三种Map(HashMap、LinkedHashMap、TreeMap)的默认排序行为及实现按键排序和按值排序的方法,每种方法结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2025-11-11

最新评论