当前位置:首页 > 后端开发 > 正文

Java如何轻松打印购物小票?

在 Java中 打印购物小票可通过控制台输出实现:使用 System.out.printf()格式化输出商品名称、单价、数量和金额,创建商品对象列表,遍历计算总价,最后打印表头和汇总信息,关键点包括对齐列宽、保留小数位数和添加分隔线增强可读性。

Java打印购物小票是零售、餐饮等系统开发的常见需求,以下是三种实用方法,涵盖不同场景(控制台调试、物理打印机输出、PDF生成),均采用标准Java API或主流库实现,确保代码健壮性和可维护性。


基础方案:控制台打印(调试用)

适用于开发阶段快速验证小票格式和逻辑。

import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; public class ConsoleReceiptPrinter { public static void main(String[] args) { // 模拟订单数据 Map<String, Double> items = new HashMap<>(); items.put("可口可乐", 3.50); items.put("薯片", 8.00); items.put("矿泉水", 2.00); printReceipt("C001", items, 0.9); // 9折优惠 } public static void printReceipt(String orderId, Map<String, Double> items, double discount) { StringBuilder sb = new StringBuilder(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 小票头部 sb.append("n============ 超市收银小票 ============n"); sb.append("订单号: ").append(orderId).append("n"); sb.append("时间: ").append(sdf.format(new Date())).append("n"); sb.append("-----------------------------------n"); // 商品列表 double subtotal = 0; for (Map.Entry<String, Double> entry : items.entrySet()) { String itemName = entry.getKey(); double price = entry.getValue(); sb.append(String.format("%-10st¥%.2fn", itemName, price)); // 左对齐商品名 subtotal += price; } // 费用计算 double discountedAmount = subtotal * discount; double savings = subtotal - discountedAmount; sb.append("-----------------------------------n"); sb.append(String.format("小计: tt¥%.2fn", subtotal)); sb.append(String.format("折扣: tt%.0f折n", discount * 10)); sb.append(String.format("优惠: tt¥%.2fn", savings)); sb.append(String.format("总计: tt¥%.2fn", discountedAmount)); sb.append("===================================n"); sb.append("感谢惠顾!客服电话:400-123-4567n"); System.out.println(sb.toString()); } }

输出效果:

Java如何轻松打印购物小票? 第1张

实战方案:连接物理打印机

使用 javax.print API 直接驱动打印机(支持USB/网络打印机)。

import javax.print.*; import javax.print.attribute.HashPrintRequestAttributeSet; import javax.print.attribute.PrintRequestAttributeSet; import javax.print.attribute.standard.Copies; import java.io.ByteArrayInputStream; import java.nio.charset.StandardCharsets; public class PhysicalPrinterService { public static void main(String[] args) { String receiptContent = generateReceiptContent(); // 生成小票文本 try { // 1. 获取打印机服务 PrintService printer = PrintServiceLookup.lookupDefaultPrintService(); if (printer == null) { throw new IllegalStateException("未找到默认打印机"); } // 2. 设置打印参数 PrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet(); attributes.add(new Copies(1)); // 打印份数 // 3. 创建打印任务 DocPrintJob job = printer.createPrintJob(); Doc doc = new SimpleDoc( new ByteArrayInputStream(receiptContent.getBytes(StandardCharsets.UTF_8)), DocFlavor.INPUT_STREAM.AUTOSENSE, null ); // 4. 执行打印 job.print(doc, attributes); System.out.println("小票打印任务已发送"); } catch (Exception e) { e.printStackTrace(); } } private static String generateReceiptContent() { // 复用控制台方案中的生成逻辑 return new ConsoleReceiptPrinter().generateReceiptString(); } }

关键注意事项:

Java如何轻松打印购物小票? 第2张

  1. 中文乱码问题

    确保打印机支持UTF-8编码,热敏打印机通常需设置为中文字库模式(如ESC/POS指令集)。

  2. 打印机选择

    可通过 PrintService[] services = PrintServiceLookup.lookupPrintServices(null, null); 列出所有打印机。

  3. 格式对齐

    使用制表符 t 或空格调整列宽,推荐固定宽度字体(如”Courier New”)。


扩展方案:生成PDF小票

使用 Apache PDFBox 库生成可保存/打印的PDF文件(需添加Maven依赖):

<dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>2.0.27</version> </dependency> import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.font.PDType1Font; import java.io.IOException; public class PdfReceiptGenerator { public static void main(String[] args) throws IOException { try (PDDocument document = new PDDocument()) { PDPage page = new PDPage(); document.addPage(page); try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) { contentStream.setFont(PDType1Font.COURIER_BOLD, 14); contentStream.beginText(); contentStream.newLineAtOffset(50, 700); // 起始坐标 // 逐行写入内容(实际项目可封装为方法) contentStream.showText("============ 超市电子小票 ============"); contentStream.newLineAtOffset(0, -20); // 下移20像素 contentStream.showText("订单号: PDF20251005001"); // 更多行省略... 参考控制台方案的格式 contentStream.endText(); } document.save("receipt.pdf"); // 保存文件 System.out.println("PDF小票已生成"); } } }


最佳实践与避坑指南

  1. 格式对齐

    • 使用 String.format() 控制列宽,

      String.format("%-20s %10.2f", productName, price)

      (左对齐商品名,右对齐价格)

  2. 字符编码

    Java如何轻松打印购物小票? 第3张

    • 物理打印时,若遇中文乱码:
      • 方案1:打印机切换至GBK/GB2312模式
      • 方案2:将文本转换为字节流时指定编码:

        receiptContent.getBytes("GB18030")

      • 打印超时处理

        job.print(doc, attributes); // 默认可能阻塞 // 建议改用异步线程,避免主线程卡死

      • 商业系统推荐

        • 复杂场景(如POS机)使用 ESC/POS指令集 直接控制打印机(需厂商文档)
        • 开源库推荐:JavaPOS、QZ Tray(支持网页调用打印机)
        • 引用说明

0