记录一次条形码相关的技术的使用。
pom依赖
<dependency><groupId>net.sf.barcode4j</groupId><artifactId>barcode4j</artifactId><version>2.1</version></dependency><dependency><groupId>e-iceblue</groupId><artifactId>spire.barcode.free</artifactId><version>5.1.1</version></dependency>
import
import com.spire.barcode.BarCodeGenerator;
import com.spire.barcode.BarCodeType;
import com.spire.barcode.BarcodeScanner;
import com.spire.barcode.BarcodeSettings;
import lombok.extern.slf4j.Slf4j;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.print.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import static java.awt.print.Printable.PAGE_EXISTS;
1.条形码生成
java中常用的条形码生成工具,我也看了不少文章,主要是:barcode4j 和 spire.barcode。
barcode4j 用法,网上给的用法我自己搬运报错了,后来我调整了写法,先生成byte[],然后再生成条形码图片。
spire.barcode设置参数生成条形码就比较简便。
这是code39条码
static byte[] generateBarCode39(String msg) {if (StringUtils.isEmpty(msg)) {return null;}Code39Bean bean = new Code39Bean();// 精细度final int dpi = 256;// module宽度final double moduleWidth = UnitConv.in2mm(1.0f / dpi);// 配置对象bean.setModuleWidth(moduleWidth);bean.setWideFactor(3);// 设置条码每一条的宽度// UnitConv 是barcode4j 提供的单位转换的实体类,用于毫米mm,像素px,英寸in,点pt之间的转换// 设置条形码高度和宽度bean.setBarHeight((double) ObjectUtils.defaultIfNull(10.00, 9.0D));// 设置两侧是否加空白bean.doQuietZone(true);String format = "image/png";ByteArrayOutputStream ous = null;byte[] imageByte;try {ous = new ByteArrayOutputStream();// 输出到流BitmapCanvasProvider canvas = new BitmapCanvasProvider(ous, format, dpi,BufferedImage.TYPE_BYTE_BINARY, false, 0);// 生成条形码bean.generateBarcode(canvas, msg);// 结束绘制canvas.finish();imageByte = ous.toByteArray();} catch (IOException e) {throw new RuntimeException(e);} finally {try {if (null != ous) {ous.close();}} catch (Exception e) {log.error("ByteArrayOutputStream流关闭失败,失败原因为:{{}}", e.getMessage());}}return imageByte;}
这是code128条码
static byte[] generateBarCode128(String msg, boolean hideText) {if (StringUtils.isEmpty(msg)) {return null;}// 如果想要其他类型的条码(CODE 39, EAN-8...)直接获取相关对象Code39Bean...等等Code128Bean bean = new Code128Bean();// 分辨率:值越大条码越长,分辨率越高。final int dpi = 256;// 设置两侧是否加空白bean.doQuietZone(true);// 设置条码每一条的宽度// UnitConv 是barcode4j 提供的单位转换的实体类,用于毫米mm,像素px,英寸in,点pt之间的转换// 设置条形码高度和宽度bean.setBarHeight((double) ObjectUtils.defaultIfNull(10.00, 9.0D));bean.setModuleWidth(UnitConv.in2mm(3.0f / dpi));// 设置文本位置(包括是否显示)if (hideText) {bean.setMsgPosition(HumanReadablePlacement.HRP_NONE);}// 设置图片类型String format = "image/png";ByteArrayOutputStream ous = null;byte[] imageByte = null;try {ous = new ByteArrayOutputStream();BitmapCanvasProvider canvas = new BitmapCanvasProvider(ous, format, dpi,BufferedImage.TYPE_BYTE_BINARY, false, 0);// 生产条形码bean.generateBarcode(canvas, msg);// 结束canvas.finish();imageByte = ous.toByteArray();} catch (IOException e) {log.error("IOException:" + e.getMessage());} finally {try {if (null != ous) {ous.close();}} catch (Exception e) {log.error("ByteArrayOutputStream流关闭失败,失败原因为:{{}}", e.getMessage());}}return imageByte;}
然后生成文件的调用
public static void generateFile(String msg, String path, String barCodeType) throws IOException {File file = new File(path);OutputStream outputStream = null;try {outputStream = new FileOutputStream(file);} catch (FileNotFoundException e) {log.error("未找到文件!");}byte[] barCodeBytes = null;if (StringUtils.equals(barCodeType, BarCodeEnum.CODE128.getCodeType())) {barCodeBytes = generateBarCode128(msg, false);} else if (StringUtils.equals(barCodeType, BarCodeEnum.CODE39.getCodeType())) {barCodeBytes = generateBarCode39(msg);}try {outputStream.write(barCodeBytes, 0, barCodeBytes.length);outputStream.flush();} catch (Exception e) {throw new RuntimeException(e);} finally {try {if (null != outputStream) {outputStream.close();}} catch (Exception e) {log.error("outputStream关闭异常!");}}}
然后是spire.barcode的生成条码
static void generateBarcode(String msg, String path, BarCodeType barCodeType) throws IOException {//保存条码为PNG图片ImageIO.write(getBarcodeImage(msg, barCodeType), "png", new File(path));}
static BufferedImage getBarcodeImage(String msg, BarCodeType barCodeType) {//创建BarcodeSettings实例BarcodeSettings settings = new BarcodeSettings();//指定条码类型 BarCodeType.Code_128settings.setType(barCodeType);//设置条码数据settings.setData(msg);//设置条码显示数据settings.setData2D(msg);//显示数据文本settings.setShowText(true);//设置数据文本显示在条码底部settings.setShowTextOnBottom(true);//设置黑白条宽度settings.setX(0.5f);//设置生成的条码图片高度settings.setImageHeight(70);//设置生成的条码图片宽度settings.setImageWidth(140);//设置边框可见settings.hasBorder(false);
// settings.setBorderColor(new Color(255, 255, 255));//设置条码边框颜色
// settings.setBorderWidth(1);//设置条码边框宽度
// settings.setBackColor(new Color(133, 218, 152));//设置条码背景色//创建BarCodeGenerator实例BarCodeGenerator barCodeGenerator = new BarCodeGenerator(settings);//根据settings生成图像数据,保存至BufferedImage实例return barCodeGenerator.generateImage();}
2.读取条形码
使用的是spire.barcode
static String getBarcode(String path, BarCodeType barCodeType) throws Exception {//使用scan方法从图片中识别Code 128条形码String[] datas = BarcodeScanner.scan(path, barCodeType);return datas[0];}
3.最后是打印条形码
static void barCodePrint(BufferedImage bufferedImage, int pageWidth, int pageHeight, int showWidth, int showHeight) {// 通俗理解就是书、文档Book book = new Book();// 设置成竖打PageFormat pf = new PageFormat();pf.setOrientation(PageFormat.PORTRAIT);// 通过Paper设置页面的空白边距和可打印区域。必须与实际打印纸张大小相符。Paper paper = new Paper();//纸张大小paper.setSize(pageWidth, pageHeight);paper.setImageableArea(0, 0, pageWidth, pageHeight);pf.setPaper(paper);// 把 PageFormat 和 Printable 添加到书中,组成一个页面book.append((graphics, pageFormat, pageIndex) -> {//将图片绘制到graphics对象中(为什么把需要打印的内容drawImage就可以实现打印自己取看值传递一引用传递的区别)graphics.drawImage(bufferedImage, 0, 0, showWidth, showHeight, null);return PAGE_EXISTS;//返回0(PAGE_EXISTS)则执行打印,返回1(NO_SUCH_PAGE)则不执行打印}, pf);// 获取打印服务对象PrinterJob job = PrinterJob.getPrinterJob();// 设置打印类job.setPageable(book);try {//可以用printDialog显示打印对话框,在用户确认后打印;也可以直接打印
// job.printDialog();job.print();} catch (PrinterException e) {e.printStackTrace();}}
main调用
String msg = "MOS123-CT1-A1";// 默认为A4纸张,对应像素宽和高分别为 595, 842barCodePrint(getBarcodeImage(msg, BarCodeType.Code_128), 595, 842, 140, 70);