【发布时间】:2020-01-06 16:09:45
【问题描述】:
我正在使用 iText7 从 pdf 文件中读取文本。这适用于第一页。在那之后,页面的内容不知何故变得混乱了。因此,在文档的第 3 页,我的行包含第 1 页和第 3 页的内容。第 2 页的文本显示的行与第 1 页完全相同(但在“现实”中,它们完全不同)。
- 第 1 页,实际:~36 行,结果 36 行 -> 很棒
- 第 2 页,实数:>50 行,结果 36 行(==第 1 页)
- 第 3 页,实数:~16 行,结果 47 行(与第 1 页的行相加和混合)
https://www.dropbox.com/s/63gy5cg1othy6ci/Dividenden_Microsoft.pdf?dl=0
为了阅读文档,我使用以下代码:
using System;
using System.Collections.Generic;
using System.Linq;
namespace StockMarket
{
class PdfReader
{
/// <summary>
/// Reads PDF file by a given path.
/// </summary>
/// <param name="path">The path to the file</param>
/// <param name="pageCount">The number of pages to read (0=all, 1 by default) </param>
/// <returns></returns>
public static DocumentTree PdfToText(string path, int pageCount=1 )
{
var pages = new DocumentTree();
using (iText.Kernel.Pdf.PdfReader reader = new iText.Kernel.Pdf.PdfReader(path))
{
using (iText.Kernel.Pdf.PdfDocument pdfDocument = new iText.Kernel.Pdf.PdfDocument(reader))
{
var strategy = new iText.Kernel.Pdf.Canvas.Parser.Listener.LocationTextExtractionStrategy();
// set up pages to read
int pagesToRead = 1;
if (pageCount > 0)
{
pagesToRead = pageCount;
}
if (pagesToRead > pdfDocument.GetNumberOfPages() || pageCount==0)
{
pagesToRead = pdfDocument.GetNumberOfPages();
}
// for each page to read...
for (int i = 1; i <= pagesToRead; ++i)
{
// get the page and save it
var page = pdfDocument.GetPage(i);
var txt = iText.Kernel.Pdf.Canvas.Parser.PdfTextExtractor.GetTextFromPage(page, strategy);
pages.Add(txt);
}
pdfDocument.Close();
reader.Close();
}
}
return pages;
}
}
/// <summary>
/// A class representing parts of a PDF document.
/// </summary>
class DocumentTree
{
/// <summary>
/// Constructor
/// </summary>
public DocumentTree()
{
Pages = new List<DocumentPage>();
}
private List<DocumentPage> _pages;
/// <summary>
/// The pages of the document
/// </summary>
public List<DocumentPage> Pages
{
get { return _pages; }
set { _pages = value; }
}
/// <summary>
/// Adds a <see cref="DocumentPage"/> to the document.
/// </summary>
/// <param name="page">The text of the <see cref="DocumentPage"/>.</param>
public void Add(string page)
{
Pages.Add(new DocumentPage(page));
}
}
/// <summary>
/// A class representing a single page of a document
/// </summary>
class DocumentPage
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="pageContent">The pages content as text</param>
public DocumentPage(string pageContent)
{
// set the content to the input
CompletePage = pageContent;
// split the content by lines
var splitter = new string[] { "\n" };
foreach (var line in CompletePage.Split(splitter, StringSplitOptions.None))
{
// add lines to the page if the content is not empty
if (!string.IsNullOrWhiteSpace(line))
{
_lines.Add(new Line(line));
}
}
}
private List<Line> _lines = new List<Line>();
/// <summary>
/// The lines of text of the <see cref="DocumentPage"/>
/// </summary>
public List<Line> Lines
{
get
{
return _lines;
}
}
/// <summary>
/// The text of the complete <see cref="DocumentPage"/>.
/// </summary>
private string CompletePage;
}
/// <summary>
/// A class representing a single line of text
/// </summary>
class Line
{
/// <summary>
/// Constructor
/// </summary>
public Line(string lineContent)
{
CompleteLine = lineContent;
}
/// <summary>
/// The words of the <see cref="Line"/>.
/// </summary>
public List<string> Words
{
get
{
return CompleteLine.Split(" ".ToArray()).Where((word)=> { return !string.IsNullOrWhiteSpace(word); }).ToList();
}
}
/// <summary>
/// The complete text of the <see cref="Line"/>.
/// </summary>
private string CompleteLine;
public override string ToString()
{
return CompleteLine;
}
}
}
页面树是一个简单的页面树,由行(读取页面以“\n”分隔)和由单词组成的行(行以“”分隔)组成,但 txt 在循环已经包含了混乱的内容(所以我的树没有引起问题)。
感谢您的帮助。
【问题讨论】:
-
PDF 文档不像 HTML 和 XML 文档那样“结构化”——PDF 实际上只是一堆绘图指令,可以以任何顺序出现以生成最终呈现的页面输出。如果 PDF 文件被标记为 PDF,您只能“正确”阅读它们 - 但是许多 PDF 生成器不标记 PDF,因此它们几乎不可能被机器读取。
-
你能分享有问题的PDF吗?
-
mkl:完成,@Dai:好的,但我认为这只会解释一页文本中的错误,而不是在显示根本不在页面上的文本时,不是吗? ?
-
慎用itext;他们的图书馆包含一个定时炸弹。该产品表面上具有商业和 AGPL 双重许可,但作者误解了 AGPL 要求您的项目也是 OSS。如果您在没有商业或 OSS 许可证密钥的私人项目中使用 itext,则 itext 将在几个月后开始发出烦人的日志垃圾邮件......正好有足够的时间让您投入生产并认为一切都很好。
标签: c# .net itext7 text-extraction