Java生成PDF字体加载异常:IDE正常打包exe后报错找不到字体文件
Java打包为exe后iTextPDF加载自定义字体失败问题解决
问题描述
IDE环境运行生成PDF的程序一切正常,但打包为.exe后,提示css/Montserrat-Regular.ttf not found错误,无法生成PDF。已尝试移除css/路径、将字体文件放置在类同目录下,且确认字体文件已包含在IntelliJ IDEA的构建产物中。
环境依赖与导入
依赖配置
implementation 'com.itextpdf:itext7-core:7.0.4'
导入包
import com.itextpdf.kernel.font.PdfFont; import com.itextpdf.kernel.pdf.PdfDocument;
已尝试的无效加载方式
- 方式一:资源流转字节数组加载
static PdfFont regular, bold; URL font_path = Thread.currentThread().getContextClassLoader().getResource("css/Montserrat-Regular.ttf"); try (InputStream is = font_path.openStream()) { byte[] bytes = StreamUtil.inputStreamToArray(is); regular = PdfFontFactory.createFont(bytes, BaseFont.IDENTITY_H, true); }
- 方式二:类加载器获取路径加载
String link1 = Thread.currentThread().getContextClassLoader().getResource("css/Montserrat-Regular.ttf").getPath(); regular = PdfFontFactory.createFont(link1, BaseFont.IDENTITY_H, true);
- 方式三:使用iText内置字体
regular = PdfFontFactory.createFont(FontConstants.HELVETICA, BaseFont.IDENTITY_H, true); bold = PdfFontFactory.createFont(FontConstants.TIMES_BOLD, BaseFont.IDENTITY_H, true);
- 方式四:通过类的类加载器获取路径加载
String path1 = (CreatePDFInvoice.class.getClassLoader().getResource("css/Montserrat-Regular.ttf").getPath()); regular = PdfFontFactory.createFont(path1, "Identity-H", true);
相关代码片段
try { String link1 = CreatePDFKUF.class.getClassLoader().getResource("css/Montserrat-Regular.ttf").getPath(); String link2 = CreatePDFKUF.class.getClassLoader().getResource("css/Montserrat-Bold.ttf").getPath(); // 弹出对话框显示路径 Functions.showOKdialogSimple("Upute", null, link1); // 此处触发错误 regular = PdfFontFactory.createFont(link1, BaseFont.IDENTITY_H, true); String folder = Functions.odabranaFirma.getNaziv(); String subfolder = "KIF"; String filename = Functions.odabranaFirma.getPDV_broj() + "_" + poreskiPeriod; theDir = new File("C:\\CSV_PDV\\" + folder + "\\" + subfolder + "\\"); System.out.println(theDir.getPath()); if (!theDir.exists()) { System.out.println("Kreiraj"); theDir.mkdirs(); } String path = "C:/CSV_PDV/" + filename + "_" + LocalDate.now() + "_" + String.valueOf(Functions.getTime()).replace(":", "") + ".pdf"; System.out.println("Naziv datoteke " + path); PdfWriter pdfWriter = new PdfWriter(path); PdfDocument pdfDocument = new PdfDocument(pdfWriter); pdfDocument.setDefaultPageSize(PageSize.A4.rotate()); Document document = new Document(pdfDocument); PageXofY event = new PageXofY(CreatePDFKUF.class, pdfDocument); pdfDocument.addEventHandler(PdfDocumentEvent.END_PAGE, event); setHeader(document); setDetails(document, poreskiPeriod); setTable(document, kufs); document.add(sp); document.add(sp); UnitValue pagesize = document.getWidth(); System.err.println(pagesize + " page size"); event.writeTotal(pdfDocument); document.close(); } catch (Exception e) { // 弹出错误对话框显示异常信息 Functions.showOKdialogSimple("Greška", null, e.getMessage()); }
报错截图
- 路径显示对话框:

- 错误提示对话框:

解决方案
核心问题
打包为exe后,资源文件内嵌在exe/jar包中,无法通过文件系统路径直接访问;类加载器getPath()返回的路径包含特殊协议前缀(如file:/)和转义字符,PdfFontFactory无法解析。
正确字体加载代码
直接通过资源输入流读取字体,完全脱离文件路径依赖:
static PdfFont regular, bold; try (InputStream regularIs = CreatePDFKUF.class.getClassLoader().getResourceAsStream("css/Montserrat-Regular.ttf"); InputStream boldIs = CreatePDFKUF.class.getClassLoader().getResourceAsStream("css/Montserrat-Bold.ttf")) { if (regularIs == null || boldIs == null) { throw new RuntimeException("字体文件未找到,请确认资源路径是否正确"); } // 直接传入输入流创建字体 regular = PdfFontFactory.createFont(regularIs, BaseFont.IDENTITY_H, true); bold = PdfFontFactory.createFont(boldIs, BaseFont.IDENTITY_H, true); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException("加载字体失败:" + e.getMessage()); }
额外注意事项
- 资源目录规范:确保
css文件夹放在src/main/resources目录下(IntelliJ IDEA会自动将该目录内容打包到classpath)。 - 打包配置检查:使用exe打包工具(如Launch4j、Inno Setup)时,确认jar包内的资源文件被完整内嵌,未遗漏
resources目录内容。 - 版本建议:将iText7版本升级至7.2.0+,修复了旧版本中部分资源加载的兼容性问题。
内容的提问来源于stack exchange,提问作者Armin Brkić
相关产品推荐
相关产品推荐

