使用ITextSharp读取供应商订单PDF时的文本提取异常问题
如何按PDF显示的行正确提取文本?
解决方案1:使用基于位置的文本提取策略
ITextSharp默认的文本提取策略不考虑文本在页面上的物理位置,容易导致行顺序错乱或内容拆分。改用LocationTextExtractionStrategy可以基于文本的坐标位置组织输出,更贴近PDF的显示行:
// 初始化位置感知的提取策略 var strategy = new LocationTextExtractionStrategy(); string pageText = PdfTextExtractor.GetTextFromPage(reader, i, strategy); // 按换行分割行 string[] lines = pageText.Split('\n');
这个策略会先按文本的Y坐标(行的垂直位置)分组,同一行内再按X坐标(水平顺序)拼接文本,能解决大部分行顺序和拆分问题。
解决方案2:自定义提取策略适配特殊布局
如果PDF有特殊排版(比如紧凑的文本块、不规则换行),可以继承LocationTextExtractionStrategy,通过自定义规则合并文本块:
public class CustomLineStrategy : LocationTextExtractionStrategy { private float _previousLineY; private readonly StringBuilder _currentLineContent = new StringBuilder(); private readonly float _lineThreshold = 2f; // 行间距阈值,根据PDF实际排版调整 public override void RenderText(TextRenderInfo renderInfo) { float currentY = renderInfo.GetBaseline().GetStartPoint()[1]; // 判断是否为新行:当前文本的Y坐标与上一行差异超过阈值则视为新行 if (Math.Abs(currentY - _previousLineY) > _lineThreshold && _currentLineContent.Length > 0) { _output.AppendLine(_currentLineContent.ToString().Trim()); _currentLineContent.Clear(); } _currentLineContent.Append(renderInfo.GetText()); _previousLineY = currentY; } public override string GetResultantText() { // 处理最后一行未添加的内容 if (_currentLineContent.Length > 0) { _output.AppendLine(_currentLineContent.ToString().Trim()); } return base.GetResultantText(); } }
使用自定义策略:
var customStrategy = new CustomLineStrategy(); string pageText = PdfTextExtractor.GetTextFromPage(reader, i, customStrategy);
可以根据实际PDF的排版调整_lineThreshold的值,确保同一行的文本块被正确合并。
解决方案3:排查PDF类型问题
如果上述方法都无效,先确认PDF的类型:
- 若是扫描图像PDF:文本提取策略无法直接读取内容,需要结合OCR工具(如Tesseract)识别图像中的文本,再进行行处理。
- 若是原生文本PDF但排版异常:可能是生成PDF时将每个单词甚至字符拆分为独立文本块,这种情况下需要进一步优化自定义策略的合并规则(比如增加X坐标的判断,确保同一行的文本按顺序拼接)。
内容的提问来源于stack exchange,提问作者Mischa Morf
相关产品推荐
相关产品推荐

