java代码pdfbox将PDF转图片后,中文乱码变成方框

文章讲述了在使用PDFBox将PDF转换为图片时遇到中文乱码的问题,通过分析日志发现是由于缺少STSong-Light字体。提供了两种解决方案:一是安装AdobeSongStd-Light字体,二是自定义FontMapperImpl类,将STSong-Light映射到已存在的AdobeSongStd-Light字体。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题现象:

使用pdfbox,将PDF转成图片后,其中的中文显示乱码(方块□□□□□)
控制台日志如下:

no glyph for 38472 (CID 04e7) in font STSong-Light

解读此行日志,先识别字体为STSong-Light,但系统中没有找到此字库,所以默认匹配到了MalgunGothic-Semilight。此字库为韩语字库,无法显示出中文,所以中文显示为□□□□□。

 上述类中的63行打了一个日志表示找不到字体。大概就是这样的:
在这里插入图片描述

if (!font.hasGlyph(code)){int cid = font.getParent().codeToCID(code);String cidHex = String.format("%04x", cid);LOG.warn("No glyph for " + code + " (CID " + cidHex + ") in font " + fontName);}

从 提出字体的地址 中看到,AdobeSongStd-Light.otf,这个字体可以解决这个问题。

解决方案1:

AdobeSongStd-Light.otf

电脑安装上面字体,C:\Windows\Fonts目录下,或者在项目中加载字体,但是当时openshift时有时加载失败,windows暂没问题。

解决方案2:(推荐)

进入pdfbox包内的如下文件

找到如下位置,可以看到substitutes内的一个映射关系,我们可以将STSong-Light映射到另一已存在的字体

FontMapperImpl() {
        this.substitutes.put("Courier", Arrays.asList("CourierNew", "CourierNewPSMT", "LiberationMono", "NimbusMonL-Regu"));
        this.substitutes.put("Courier-Bold", Arrays.asList("CourierNewPS-BoldMT", "CourierNew-Bold", "LiberationMono-Bold", "NimbusMonL-Bold"));
        this.substitutes.put("Courier-Oblique", Arrays.asList("CourierNewPS-ItalicMT", "CourierNew-Italic", "LiberationMono-Italic", "NimbusMonL-ReguObli"));
        this.substitutes.put("Courier-BoldOblique", Arrays.asList("CourierNewPS-BoldItalicMT", "CourierNew-BoldItalic", "LiberationMono-BoldItalic", "NimbusMonL-BoldObli"));
        this.substitutes.put("Helvetica", Arrays.asList("ArialMT", "Arial", "LiberationSans", "NimbusSanL-Regu"));
        this.substitutes.put("Helvetica-Bold", Arrays.asList("Arial-BoldMT", "Arial-Bold", "LiberationSans-Bold", "NimbusSanL-Bold"));
        this.substitutes.put("Helvetica-Oblique", Arrays.asList("Arial-ItalicMT", "Arial-Italic", "Helvetica-Italic", "LiberationSans-Italic", "NimbusSanL-ReguItal"));
        this.substitutes.put("Helvetica-BoldOblique", Arrays.asList("Arial-BoldItalicMT", "Helvetica-BoldItalic", "LiberationSans-BoldItalic", "NimbusSanL-BoldItal"));
        this.substitutes.put("Times-Roman", Arrays.asList("TimesNewRomanPSMT", "TimesNewRoman", "TimesNewRomanPS", "LiberationSerif", "NimbusRomNo9L-Regu"));
        this.substitutes.put("Times-Bold", Arrays.asList("TimesNewRomanPS-BoldMT", "TimesNewRomanPS-Bold", "TimesNewRoman-Bold", "LiberationSerif-Bold", "NimbusRomNo9L-Medi"));
        this.substitutes.put("Times-Italic", Arrays.asList("TimesNewRomanPS-ItalicMT", "TimesNewRomanPS-Italic", "TimesNewRoman-Italic", "LiberationSerif-Italic", "NimbusRomNo9L-ReguItal"));
        this.substitutes.put("Times-BoldItalic", Arrays.asList("TimesNewRomanPS-BoldItalicMT", "TimesNewRomanPS-BoldItalic", "TimesNewRoman-BoldItalic", "LiberationSerif-BoldItalic", "NimbusRomNo9L-MediItal"));
        this.substitutes.put("Symbol", Arrays.asList("Symbol", "SymbolMT", "StandardSymL"));
        this.substitutes.put("ZapfDingbats", Arrays.asList("ZapfDingbatsITC", "Dingbats", "MS-Gothic"));
        Iterator var1 = Standard14Fonts.getNames().iterator();

先按照这个FontMapperImpl类在自己的项目中建立一个和这个路径完全一致的FontMapperImpl类,代码内容复制过来。

并在substitutes中增加一个STSong-Light的映射关系,映射到我的环境中已有的AdobeSongStd-Light字体。

this.substitutes.put("STSong-Light", Arrays.asList("AdobeSongStd-Light"));

重新执行就成功了。

<think>好的,用户的问题是关于在Java中生成PDF文件,并实现在框内添加对勾符号(√)。我需要先确定用户的需求,然后找到合适的库和方法来解决这个问题。 首先,用户提到了生成PDFJava中常用的库有iText和Apache PDFBox。这两个库都是比较成熟的选择,但iText在功能上可能更强大一些,尤其是在处理表单和复选框方面。不过需要注意iText的许可证问题,商业用途可能需要购买许可证,而Apache PDFBox是开源的,更适合开源项目。 接下来,用户需要添加对勾符号到复选框内。这里的关键是如何在PDF中正确渲染这个符号,特别是字体支持的问题。标准的PDF字体可能不包含对勾符号,或者编码方式不同,导致显示问题。因此,可能需要使用支持Unicode的字体,比如Arial Unicode MS或其他包含对勾符号的字体。同时,需要注意字符编码,确保使用正确的Unicode码点,如“\u2713”或“\u2714”。 然后,我需要考虑用户可能的实际应用场景,比如生成表单、报告或者需要用户交互的PDF文档。复选框通常用于表单中,用户可能需要将表单字段设置为已勾选状态,或者静态地在PDF上绘制对勾符号。如果是表单字段,使用iText的AcroForm功能可能更合适;如果是静态内容,直接绘制文本或图形即可。 用户可能遇到的问题包括字体不支持对勾符号,导致显示为方框乱码,或者复选框的位置和大小调整不当。因此,在示例代码中需要明确指定字体,并确保字体文件可用。同时,可能需要处理不同PDF库之间的API差异,比如iText和PDFBox在创建复选框的方法上有所不同。 此外,用户可能对许可证有疑问,尤其是如果项目是商业性质的,需要提醒他们注意iText的AGPL许可证,可能需要购买商业许可证,而PDFBox的Apache许可证则更为宽松。 最后,生成相关问题需要考虑用户可能进一步的需求,比如如何自定义复选框样式、处理动态表单、导出数据等,以及与其他库的对比和性能问题。这些相关问题可以帮助用户更深入地理解和应用解决方案。</think>### Java生成带勾选符号的PDF实现方法 在Java中生成PDF并添加勾选符号,推荐使用**iText**或**Apache PDFBox**库。以下是两种实现方案: --- #### 方案一:使用iText库(推荐版本7+) ```java import com.itextpdf.kernel.pdf.*; import com.itextpdf.layout.element.Paragraph; import com.itextpdf.layout.Document; public class PdfWithCheckbox { public static void main(String[] args) throws Exception { PdfWriter writer = new PdfWriter("output.pdf"); PdfDocument pdf = new PdfDocument(writer); Document doc = new Document(pdf); // 添加带勾选框的段落 Paragraph p = new Paragraph("同意条款: ") .add(new Paragraph("✓").setFont(PdfFontFactory.createFont(StandardFonts.HELVETICA))); doc.add(p); doc.close(); } } ``` #### 方案二:使用Apache PDFBox ```java 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; public class PdfCheckboxExample { public static void main(String[] args) throws Exception { PDDocument doc = new PDDocument(); PDPage page = new PDPage(); doc.addPage(page); try (PDPageContentStream content = new PDPageContentStream(doc, page)) { content.beginText(); content.setFont(PDType1Font.HELVETICA_BOLD, 12); content.newLineAtOffset(100, 700); content.showText("同意条款: ✓"); content.endText(); } doc.save("checkbox.pdf"); doc.close(); } } ``` --- ### 关键问题说明 1. **符号显示问题**:必须使用支持Unicode的字体(如`ArialUnicodeMS`),否则勾号可能显示为方块。iText中可通过`PdfFontFactory.createFont("fonts/arialuni.ttf")`指定自定义字体[^1]。 2. **复选框对齐**:精确控制位置时需使用`content.newLineAtOffset(x,y)`调整坐标。 3. **动态表单字段**:iText支持创建可交互的PDF表单复选框: ```java PdfButtonFormField checkbox = PdfFormField.createCheckBox(pdf, new Rectangle(100,700,15,15), "agree", "Yes"); checkbox.setValue("Yes"); PdfAcroForm.getAcroForm(pdf, true).addField(checkbox); ``` --- ### 运行环境配置(以Maven为例) ```xml <!-- iText 7依赖 --> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext7-core</artifactId> <version>7.2.5</version> </dependency> <!-- PDFBox依赖 --> <dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>2.0.29</version> </dependency> ``` ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值