如何通过iText7的RegexBasedLocationExtractionStrategy获取匹配文本的字体名与字号
解决iText7中提取文本时同时获取字体名称和字号的问题
要拿到匹配文本的字体名称和字号,你得自定义一个文本提取策略,继承RegexBasedLocationExtractionStrategy并扩展功能,在处理文本渲染事件时捕获字体属性。
实现步骤
- 自定义提取策略类:重写事件处理方法,记录每个匹配文本片段的字体名称、字号,同时保留原有的位置信息。
- 使用自定义策略提取信息:实例化自定义策略,传入正则表达式,遍历PDF页面获取所有匹配片段的完整信息。
- 基于提取的信息进行文本替换:利用获取到的字体和位置信息,生成新的文本覆盖原位置。
代码示例
自定义提取策略类
using iText.Kernel.Pdf.Canvas.Parser; using iText.Kernel.Pdf.Canvas.Parser.Data; using iText.Kernel.Pdf.Canvas.Parser.Listener; using System.Collections.Generic; using System.Text.RegularExpressions; public class RegexWithFontExtractionStrategy : RegexBasedLocationExtractionStrategy { // 存储匹配到的文本的完整信息 public List<TextWithFontInfo> MatchedTextInfos { get; } = new List<TextWithFontInfo>(); public RegexWithFontExtractionStrategy(Regex regex) : base(regex) { } public override void EventOccurred(IEventData data, EventType type) { base.EventOccurred(data, type); if (type == EventType.RENDER_TEXT) { TextRenderInfo renderInfo = (TextRenderInfo)data; string text = renderInfo.GetText(); // 检查当前文本片段是否匹配正则 Match match = GetRegex().Match(text); if (match.Success) { // 获取字体名称和字号 string fontName = renderInfo.GetFont().GetFontProgram().GetFontNames().GetFontName(); float fontSize = renderInfo.GetFontSize(); // 获取文本位置矩形 var rect = renderInfo.GetDescentLine().GetBoundingRectangle(); MatchedTextInfos.Add(new TextWithFontInfo { Text = match.Value, BoundingRect = rect, FontName = fontName, FontSize = fontSize }); } } } } // 存储文本及字体信息的实体类 public class TextWithFontInfo { public string Text { get; set; } public iText.Kernel.Geom.Rectangle BoundingRect { get; set; } public string FontName { get; set; } public float FontSize { get; set; } }
使用自定义策略提取并替换文本
using iText.Kernel.Pdf; using iText.Kernel.Pdf.Canvas; using iText.Layout; using iText.Layout.Element; using iText.Layout.Properties; // 读取原PDF并创建输出PDF PdfReader reader = new PdfReader("input.pdf"); PdfWriter writer = new PdfWriter("output.pdf"); PdfDocument pdfDoc = new PdfDocument(reader, writer); // 定义要搜索的正则表达式 Regex regex = new Regex("要替换的文本"); for (int pageNum = 1; pageNum <= pdfDoc.GetNumberOfPages(); pageNum++) { PdfPage page = pdfDoc.GetPage(pageNum); // 实例化自定义提取策略 RegexWithFontExtractionStrategy strategy = new RegexWithFontExtractionStrategy(regex); PdfCanvasProcessor processor = new PdfCanvasProcessor(strategy); processor.ProcessPageContent(page); // 遍历所有匹配的文本信息,执行替换 foreach (var textInfo in strategy.MatchedTextInfos) { // 用白色矩形覆盖原文本 PdfCanvas canvas = new PdfCanvas(page); canvas.SaveState() .SetFillColor(iText.Kernel.Colors.ColorConstants.WHITE) .Rectangle(textInfo.BoundingRect) .Fill() .RestoreState(); // 使用原字体和字号添加替换后的文本 Document doc = new Document(pdfDoc); Paragraph newText = new Paragraph("替换后的文本") .SetFontSize(textInfo.FontSize) .SetFont(textInfo.FontName) .SetFixedPosition(textInfo.BoundingRect.GetLeft(), textInfo.BoundingRect.GetBottom(), textInfo.BoundingRect.GetWidth()); doc.Add(newText); doc.Close(); } } // 关闭资源 pdfDoc.Close(); reader.Close(); writer.Close();
注意事项
- 部分PDF中的字体是嵌入的子集,字体名称可能带有后缀(如
ArialMT),这是正常现象,iText会正确识别。 - 如果替换后的文本长度与原文本差异较大,需要调整矩形宽度或处理换行,避免内容溢出。
- 确保已安装iText7相关NuGet包:
iText7.Core、iText7.Layout。
内容的提问来源于stack exchange,提问作者zhusp
相关产品推荐
相关产品推荐

