iText 7.1.0 for Java:非断字连字符部分场景失效求助
解决iText中非断字连字符(\u2011)在德语词汇前失效的问题
我来帮你拆解这个问题的核心原因,以及对应的实用解决方案:
问题根源
你使用的\u2011是非断字连字符(Non-breaking Hyphen),设计初衷就是阻止连字符两端的内容被拆分换行,但在99\u2011Tage、99\u2011Frage这类组合里失效,而99\u2011Days正常,核心原因在于:
- 你给段落设置了德语断字规则
HyphenationConfig("de", "DE", 2, 2),iText的断字引擎会优先对德语词汇应用语言专属的断字逻辑——它会把99\u2011Tage当作一个复合词尝试断字,从而忽略了非断字连字符的作用。 - 英文词汇
Days没有对应的德语断字规则,断字引擎不会处理它,所以非断字连字符的效果能正常生效。
解决方案
这里提供三种适配不同场景的解决方法,你可以按需选择:
方法一:给需要保护的文本块单独禁用断字
把99\u2011Tage、99\u2011Frage这类需要阻止换行的文本单独提取为Text对象,给它们设置setHyphenation(null),跳过断字规则,让非断字连字符发挥作用:
// 拆分文本,单独处理需要保护的部分 Paragraph paragraph = new Paragraph() .add(new Text("Dies ist ein Satz in deutscher Sprache. An hm kann man sehen, ob alle Buchstaben da sind. Und der Umbruch? ") .setFont(font).setFontSize(10)) .add(new Text("99\u2011Tage-Kaiser") .setFont(font).setFontSize(10).setHyphenation(null)) .add(new Text("\nDies ist ein Satz in deutscher Sprache. An hm kann man sehen, ob alle Buchstaben da sind. Und der Umbruch? 99\u2011Days-Kaiser.\n") .setFont(font).setFontSize(10)) .add(new Text("Dies ist ein Satz in deutscher Sprache. An hm kann man sehen, ob alle Buchstaben da sind. Und der Umbruch? ") .setFont(font).setFontSize(10)) .add(new Text("99\u2011Frage-Kaiser") .setFont(font).setFontSize(10).setHyphenation(null)); // 给整个段落保留德语断字规则 paragraph.setHyphenation(new HyphenationConfig("de", "DE", 2, 2));
方法二:用零宽非断空格强化非断字效果
在非断字连字符的前后添加零宽非断空格(\uFEFF),这个字符不会显示,但会强制iText把数字、连字符、名词视为一个不可拆分的整体:
Text text = new Text( "Dies ist ein Satz in deutscher Sprache. An hm kann man sehen, ob alle Buchstaben da sind. Und der Umbruch? 99\uFEFF\u2011\uFEFFTage-Kaiser.\n" + "Dies ist ein Satz in deutscher Sprache. An hm kann man sehen, ob alle Buchstaben da sind. Und der Umbruch? 99\u2011Days-Kaiser.\n" + "Dies ist ein Satz in deutscher Sprache. An hm kann man sehen, ob alle Buchstaben da sind. Und der Umbruch? 99\uFEFF\u2011\uFEFFFrage-Kaiser.\n");
方法三:自定义断字字典(进阶)
如果你的项目中有大量这类数字+德语名词的组合,可以自定义德语断字字典,把99-Tage、99-Frage这类词标记为不可断字。不过这个方法需要修改iText的断字配置文件,适合全局统一处理的场景,操作相对复杂。
完整修改后的代码(方法一示例)
import java.awt.Desktop; import java.io.File; import java.io.IOException; import com.itextpdf.io.font.PdfEncodings; import com.itextpdf.kernel.font.PdfFont; import com.itextpdf.kernel.font.PdfFontFactory; import com.itextpdf.kernel.pdf.PdfDocument; import com.itextpdf.kernel.pdf.PdfWriter; import com.itextpdf.layout.Document; import com.itextpdf.layout.element.Paragraph; import com.itextpdf.layout.element.Text; import com.itextpdf.layout.hyphenation.HyphenationConfig; public class problem1 { public static void main(String[] args) throws IOException { String fnFont = "src/main/resources/fonts/arialuni.ttf"; String fnPdf = "results/problem1.pdf"; PdfWriter writer = new PdfWriter(fnPdf); PdfDocument pdf = new PdfDocument(writer); Document document = new Document(pdf); PdfFont font = PdfFontFactory.createFont(fnFont, PdfEncodings.IDENTITY_H, true); // 构建段落,单独处理需要保护的文本块 Paragraph paragraph = new Paragraph() .add(new Text("Dies ist ein Satz in deutscher Sprache. An hm kann man sehen, ob alle Buchstaben da sind. Und der Umbruch? ") .setFont(font).setFontSize(10)) .add(new Text("99\u2011Tage-Kaiser") .setFont(font).setFontSize(10).setHyphenation(null)) .add(new Text("\nDies ist ein Satz in deutscher Sprache. An hm kann man sehen, ob alle Buchstaben da sind. Und der Umbruch? 99\u2011Days-Kaiser.\n") .setFont(font).setFontSize(10)) .add(new Text("Dies ist ein Satz in deutscher Sprache. An hm kann man sehen, ob alle Buchstaben da sind. Und der Umbruch? ") .setFont(font).setFontSize(10)) .add(new Text("99\u2011Frage-Kaiser") .setFont(font).setFontSize(10).setHyphenation(null)); // 给整个段落设置德语断字规则 paragraph.setHyphenation(new HyphenationConfig("de", "DE", 2, 2)); document.add(paragraph); document.close(); pdf.close(); Desktop.getDesktop().open(new File(fnPdf)); } }
内容的提问来源于stack exchange,提问作者Dirk Kampfmeier
相关产品推荐
相关产品推荐

