特定PDF中C# RenderInfo.GetText()无法获取换行,如何解决?
需求与问题
我的目标
我需要在PDF中搜索特定文本,该文本有时包含换行符。在本例中,我希望提取PDF中某标记矩形区域内的3行带换行的文本。
我的代码
我使用iTextSharp 5.5.13.3编写了如下C#代码:
var fontStrategy = new GetFontsExtractionStrategy(); using (var reader = new PdfReader("C:\\pdf.pdf")) { var text = string.Empty; for (int page = 1; page <= reader.NumberOfPages; page++) { var ex = PdfTextExtractor.GetTextFromPage(reader, page, fontStrategy); } } Logging.LogInfo($"PDF text: {fontStrategy.lastChunks}"); public class GetFontsExtractionStrategy : LocationTextExtractionStrategy { public string lastChunks; public override void RenderText(TextRenderInfo renderInfo) { var txt = renderInfo.GetText(); lastChunks += txt; } }
当前结果
lastChunks中提取到的相关文本为:
Unvani (T�zel Kisiler doldurulacaktir.) (Kisaltma yapilmadan Ticaret Sicilinde yer aldigi bi�imde yazilacaktir)
预期结果
希望提取到带正确换行的文本:
Unvani (T�zel Kisiler doldurulacaktir.) (Kisaltma yapilmadan Ticaret Sicilinde yer aldigi bi�imde yazilacaktir)
我的问题
如何获取包含正确换行的文本?必要时我也可以更换PDF处理库,恳请提供解决方案!
解决方案
方法1:优化iTextSharp的文本提取策略
你的自定义提取策略仅简单拼接文本,未考虑PDF中文字的位置信息(如行间距、Y坐标变化)。可通过对比相邻文本块的Y坐标判断换行:
修改提取策略类,添加换行判断逻辑:
public class LineBreakExtractionStrategy : LocationTextExtractionStrategy { public string ExtractedText { get; private set; } = string.Empty; private float? _lastY; // 换行阈值,需根据PDF字体大小调整,字体12号时建议设为5左右 private const float LineBreakThreshold = 5f; public override void RenderText(TextRenderInfo renderInfo) { var currentY = renderInfo.GetBaseline().GetStartPoint()[1]; // 当当前文本块与上一块Y坐标差异超过阈值时添加换行 if (_lastY.HasValue && Math.Abs(currentY - _lastY.Value) > LineBreakThreshold) { ExtractedText += Environment.NewLine; } ExtractedText += renderInfo.GetText(); _lastY = currentY; } }
使用时替换原策略:
var lineBreakStrategy = new LineBreakExtractionStrategy(); using (var reader = new PdfReader("C:\\pdf.pdf")) { for (int page = 1; page <= reader.NumberOfPages; page++) { PdfTextExtractor.GetTextFromPage(reader, page, lineBreakStrategy); } } Logging.LogInfo($"带换行的PDF文本: {lineBreakStrategy.ExtractedText}");
方法2:更换为PdfPig库
如果iTextSharp调整效果不佳,可尝试开源.NET库PdfPig,它默认保留文本的换行结构:
- 通过NuGet安装:
Install-Package PdfPig - 提取文本代码:
using UglyToad.PdfPig; using UglyToad.PdfPig.Content; using (var document = PdfDocument.Open("C:\\pdf.pdf")) { foreach (Page page in document.GetPages()) { string pageText = page.Text; Logging.LogInfo($"页面文本: {pageText}"); } }
PdfPig会根据PDF布局自动识别换行,多数场景下可直接得到符合预期的带换行文本。
方法3:提取指定矩形区域的文本
若仅需特定矩形内的文本,可结合坐标过滤(以iTextSharp为例):
public class RegionTextExtractionStrategy : LocationTextExtractionStrategy { public string ExtractedText { get; private set; } = string.Empty; private readonly Rectangle _targetRegion; private float? _lastY; private const float LineBreakThreshold = 5f; public RegionTextExtractionStrategy(Rectangle targetRegion) { _targetRegion = targetRegion; } public override void RenderText(TextRenderInfo renderInfo) { var textRect = renderInfo.GetDescentLine().GetBoundingRectangle(); // 过滤目标区域外的文本 if (!_targetRegion.Intersects(textRect)) { return; } var currentY = renderInfo.GetBaseline().GetStartPoint()[1]; if (_lastY.HasValue && Math.Abs(currentY - _lastY.Value) > LineBreakThreshold) { ExtractedText += Environment.NewLine; } ExtractedText += renderInfo.GetText(); _lastY = currentY; } }
使用时指定目标矩形(坐标以PDF页面左下角为原点,需根据实际区域调整):
// 示例区域:x:100-500,y:200-400 var targetRegion = new Rectangle(100, 200, 500, 400); var regionStrategy = new RegionTextExtractionStrategy(targetRegion); using (var reader = new PdfReader("C:\\pdf.pdf")) { PdfTextExtractor.GetTextFromPage(reader, 1, regionStrategy); } Logging.LogInfo($"区域内带换行文本: {regionStrategy.ExtractedText}");
内容的提问来源于stack exchange,提问作者Patrick
相关产品推荐
相关产品推荐

