You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Apache PDFBox在PDF中写入表情符号

PDFBox写入文本与表情符号时表情缺失解决方案

表情缺失的核心原因是PDF默认的14种标准字体均不包含表情符号对应的Unicode字形,需更换支持表情的字体并调整渲染逻辑,具体操作如下:

前置检查

  • 先升级PDFBox到2.0.27及以上稳定版本,低版本对多字节Unicode、彩色表情的支持存在缺陷
  • 准备支持全量表情的字体,优先选开源无版权风险的Noto Color Emoji,也可以用系统自带的Segoe UI Emoji(Windows)、Apple Color Emoji(macOS)

核心实现步骤

1. 嵌入字体到PDF

必须将字体嵌入PDF,否则接收方设备无对应字体时仍会出现显示缺失,加载字体示例代码:

// 第三个参数设为true代表将字体嵌入PDF文件
PDType0Font emojiFont = PDType0Font.load(document, new File("字体文件本地路径"), true);
// 同时加载你用于渲染普通文本的常规字体,比如思源黑体、宋体等
PDType0Font textFont = PDType0Font.load(document, new File("常规字体本地路径"), true);

2. 分段渲染混合内容

常规文本和表情需要用不同字体渲染,所以要先拆分内容中的普通字符和表情字符,分别匹配对应字体后逐个渲染:

PDPageContentStream contentStream = new PDPageContentStream(document, page);
String content = "测试普通文本😊 混合表情内容😎";
int length = content.length();
float currentX = 100; // 初始绘制X坐标
float currentY = 700; // 初始绘制Y坐标
float fontSize = 12f;

for (int i = 0; i < length; ) {
    int codePoint = content.codePointAt(i);
    int charCount = Character.charCount(codePoint);
    String currentPart = content.substring(i, i + charCount);
    // JDK11及以上可直接用Character.isEmoji()判断,低版本可以自行维护表情Unicode范围判断逻辑
    boolean isEmoji = Character.isEmoji(codePoint);

    contentStream.beginText();
    contentStream.setFont(isEmoji ? emojiFont : textFont, fontSize);
    contentStream.newLineAtOffset(currentX, currentY);
    contentStream.showText(currentPart);
    contentStream.endText();

    // 计算当前片段宽度,更新下一段内容的X坐标,避免内容重叠
    float partWidth = (isEmoji ? emojiFont : textFont).getStringWidth(currentPart) / 1000 * fontSize;
    currentX += partWidth;

    i += charCount;
}
contentStream.close();

常见异常排查

  • 表情显示为黑白:更换带彩色矢量信息的表情字体,同时确认PDFBox版本在2.0.27及以上
  • 表情和文本排版错位:可以将表情的字号调整为比普通文本大1-2号,适配显示比例
  • 仍显示空白方块:提前在字体查看工具中确认你使用的字体确实包含对应表情的字形,部分精简版字体会删减冷门表情

内容的提问来源于stack exchange,提问作者swapnil nd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 15:36:04