Читання вмісту PDF за допомогою dll itextsharp у VB.NET або C #


80

Як я можу прочитати вміст PDF за допомогою itextsharp за допомогою класу Pdfreader. Мій PDF може містити звичайний текст або зображення тексту.


iTextSharp тепер називається "iText 7 для .NET" або "itext7-dotnet" на github: link . Рекомендується додати itext7 з Nuget до свого рішення.
Пітер Хубер,

Відповіді:


184
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;
using System.IO;

public string ReadPdfFile(string fileName)
{
    StringBuilder text = new StringBuilder();

    if (File.Exists(fileName))
    {
        PdfReader pdfReader = new PdfReader(fileName);

        for (int page = 1; page <= pdfReader.NumberOfPages; page++)
        {
            ITextExtractionStrategy strategy = new SimpleTextExtractionStrategy();
            string currentText = PdfTextExtractor.GetTextFromPage(pdfReader, page, strategy);

            currentText = Encoding.UTF8.GetString(ASCIIEncoding.Convert(Encoding.Default, Encoding.UTF8, Encoding.Default.GetBytes(currentText)));
            text.Append(currentText);
        }
        pdfReader.Close();
    }
    return text.ToString();
}

16
Це слід позначити як рішення! Для мене це чудово працює.
Картер Медлін,

1
Будь-яка конкретна причина pdfReader.Close (); відбувається всередині циклу for?
ч. 00 м.

8
чому взагалі використовувати .Close (), а ніusing (var pdfReader = ...) {}
Себастьян

2
Крім того, ASCIIEncoding.Convertмає бути так, Encoding.Convertяк це є статичним методом
Себастьян

Якщо кому-небудь потрібен код, подібний до наведеного вище, покрокова реалізація для читання тексту pdf на C #, ось посилання, qawithexperts.com/article/c-sharp/… спасибі
user3559462

15

LGPL / FOSS iTextSharp 4.x

var pdfReader = new PdfReader(path); //other filestream etc
byte[] pageContent = _pdfReader .GetPageContent(pageNum); //not zero based
byte[] utf8 = Encoding.Convert(Encoding.Default, Encoding.UTF8, pageContent);
string textFromPage = Encoding.UTF8.GetString(utf8);

Жодна з інших відповідей не була для мене корисною, вони, схоже, націлені на AGPL v5 iTextSharp. Я ніколи не міг знайти жодного посилання на SimpleTextExtractionStrategyабоLocationTextExtractionStrategy версію FOSS у ній.

Ще щось, що може бути дуже корисним у поєднанні з цим:

const string PdfTableFormat = @"\(.*\)Tj";
Regex PdfTableRegex = new Regex(PdfTableFormat, RegexOptions.Compiled);

List<string> ExtractPdfContent(string rawPdfContent)
{
    var matches = PdfTableRegex.Matches(rawPdfContent);

    var list = matches.Cast<Match>()
        .Select(m => m.Value
            .Substring(1) //remove leading (
            .Remove(m.Value.Length - 4) //remove trailing )Tj
            .Replace(@"\)", ")") //unencode parens
            .Replace(@"\(", "(")
            .Trim()
        )
        .ToList();
    return list;
}

Це витягне лише текстові дані з PDF-файлу, якщо відображений текст Foo(bar)буде закодовано в PDF як (Foo\(bar\))Tj, цей метод повернеться, Foo(bar)як очікувалося. Цей метод вилучить багато додаткової інформації, наприклад координати місцезнаходження, із необробленого вмісту PDF.


1
Ви маєте рацію, до того, як вилучення тексту 5.xx було присутнім у iText лише як доказ концепції, а в iTextSharp - зовсім. З огляду на це, код, який ви представляєте, працює лише у дуже примітивно побудованих PDF-файлах (використовуючи шрифти з кодуванням ASCII та Tj як лише оператор малювання тексту). Він може бути використаний у дуже контрольованих середовищах (у яких ви можете отримати лише такі примітивні PDF-файли), але не в цілому.
mkl

Правильним виразом регулярних виразів є: (? <= () (. *?) (? =) Tj)
Дієго,

6

Ось рішення VB.NET на основі рішення ShravankumarKumar.

Це надасть ТІЛЬКИ текст. Зображення - це вже інша історія.

Public Shared Function GetTextFromPDF(PdfFileName As String) As String
    Dim oReader As New iTextSharp.text.pdf.PdfReader(PdfFileName)

    Dim sOut = ""

    For i = 1 To oReader.NumberOfPages
        Dim its As New iTextSharp.text.pdf.parser.SimpleTextExtractionStrategy

        sOut &= iTextSharp.text.pdf.parser.PdfTextExtractor.GetTextFromPage(oReader, i, its)
    Next

    Return sOut
End Function

Коли я пробую це у своєму PDF-файлі, з’являється повідомлення про помилку: "Значення не може бути нульовим. Ім'я параметра: значення". Будь-яка ідея, про що йдеться?
Avi

sOut & = iTextSharp.text.pdf.parser.PdfTextExtractor.GetTextFromPage (oReader, i, його). Крім того, я щось з’ясував щодо цієї помилки. Якщо я вийму це з циклу і проаналізую окремі сторінки, він працює на одній, а не на іншій сторінці. Єдина різниця між ними, яку я можу сказати, полягає в тому, що на проблемній сторінці є зображення (які мені не потрібні).
Avi

Якщо ви хочете поглянути на PDF, я можу надіслати його вам.
Avi

Я використовую .Net 4.0 та itextsharp 5.1.2.0 (Щойно завантажено). Те саме з вами?
Картер Медлін,

.Net 3.5 та itextsharp 5.1.1. Я оновлю і перевірю, чи це вирішено.
Avi

5

У моєму випадку я просто хотів отримати текст із певної області PDF-документа, тому використав прямокутник навколо області та витягнув із нього текст. У зразку нижче координати вказані для всієї сторінки. У мене немає інструментів для створення PDF-файлів, тому, коли прийшов час звузити прямокутник до конкретного місця, я зробив кілька здогадок щодо координат, поки область не була знайдена.

Rectangle _pdfRect = new Rectangle(0f, 0f, 612f, 792f); // Entire page - PDF coordinate system 0,0 is bottom left corner.  72 points / inch
RenderFilter _renderfilter = new RegionTextRenderFilter(_pdfRect);
ITextExtractionStrategy _strategy = new FilteredTextRenderListener(new LocationTextExtractionStrategy(), _filter);
string _text = PdfTextExtractor.GetTextFromPage(_pdfReader, 1, _strategy);

Як зазначалося у наведених вище коментарях, отриманий текст не підтримує жодного форматування, знайденого в документі PDF, однак, я був радий, що він зберег повернення каретки. У моєму випадку в тексті було достатньо констант, щоб я зміг витягти потрібні мені значення.


0

Тут покращена відповідь ShravankumarKumar. Я створив спеціальні класи для сторінок, щоб ви могли отримувати доступ до слів у форматі PDF на основі текстових рядків та слова в цьому рядку.

using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;

//create a list of pdf pages
var pages = new List<PdfPage>();

//load the pdf into the reader. NOTE: path can also be replaced with a byte array
using (PdfReader reader = new PdfReader(path))
{
    //loop all the pages and extract the text
    for (int i = 1; i <= reader.NumberOfPages; i++)
    {
        pages.Add(new PdfPage()
        {
           content = PdfTextExtractor.GetTextFromPage(reader, i)
        });
    }
}

//use linq to create the rows and words by splitting on newline and space
pages.ForEach(x => x.rows = x.content.Split('\n').Select(y => 
    new PdfRow() { 
       content = y,
       words = y.Split(' ').ToList()
    }
).ToList());

Спеціальні класи

class PdfPage
{
    public string content { get; set; }
    public List<PdfRow> rows { get; set; }
}


class PdfRow
{
    public string content { get; set; }
    public List<string> words { get; set; }
}

Тепер ви можете отримати слово за рядком та індекс слова.

string myWord = pages[0].rows[12].words[4];

Або використовуйте Linq, щоб знайти рядки, що містять конкретне слово.

//find the rows in a specific page containing a word
var myRows = pages[0].rows.Where(x => x.words.Any(y => y == "myWord1")).ToList();

//find the rows in all pages containing a word
var myRows = pages.SelectMany(r => r.rows).Where(x => x.words.Any(y => y == "myWord2")).ToList();

-1
Public Sub PDFTxtToPdf(ByVal sTxtfile As String, ByVal sPDFSourcefile As String)
        Dim sr As StreamReader = New StreamReader(sTxtfile)
    Dim doc As New Document()
    PdfWriter.GetInstance(doc, New FileStream(sPDFSourcefile, FileMode.Create))
    doc.Open()
    doc.Add(New Paragraph(sr.ReadToEnd()))
    doc.Close()
End Sub

1
Питання просить прочитати файл PDF, ваша відповідь створює його!
AaA
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.