Несколько потоков, извлекающих текст из iText PDF

Я пытался ускорить извлечение текста из файлов PDF. Я пробовал SnowTide's PDFTextStream, Это было медленнее, чем iText на моем компьютере.

Моя последняя попытка - использовать несколько потоков.

Я инициализирую PdfReader с байтовым массивом вместо имени файла. Это сделано для того, чтобы я мог избежать задержки ввода-вывода, запустив все это в память. Из того, что я могу сказать, iText получает данные из файла по мере необходимости. С байтовым массивом такой проблемы быть не должно.

Я использую потоки, чтобы извлечь несколько диапазонов страниц.

Тем не менее, это сделало это намного медленнее. Использование одного потока против пяти быстрее. Я не знаю, почему это так. Из того, что я могу сказать, "бутылочное горлышко" извлекает саму страницу PdfTextExtractor.getTextFromPage(mReader, i), Я рассчитал цикл for, который объединяет текст потока и не влияет на общее время.

Мой вопрос: почему это медленнее и как я могу сделать это быстрее?

Доступ к тому же PdfReader создавая узкое место? Должен ли я инициализировать несколько PdfReaderс тем же байтовым массивом? Я ошибаюсь в каком-либо из моих исследований? Если у кого-то есть предложения по поводу совершенно новых открытых экстракторов PDF или другие предложения, это было бы здорово!

import java.io.*;

import com.itextpdf.text.pdf.parser.PdfTextExtractor; 
import com.itextpdf.text.pdf.PdfReader;
import java.nio.channels.FileChannel;
import java.nio.MappedByteBuffer;

public class PDFParser
{
    private PdfReader mReader;
    private int numPages;
    private String bodyText;

    public PDFParser(String pdf)
    throws IOException
    {
    /*
      scrapped this
               mReader = new PdfReader(pdf);
      and replaced with the following. 
      From what I can tell Pdfreader with the above constructor 
      probably uses a stream to get the pages one at a time.
      I want to load it all into memory to increase the speed.
    */

        final FileChannel channel = new FileInputStream(pdf).getChannel();
        MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
        byte[] byteArray = new byte[buffer.remaining()];
        buffer.get(byteArray);
        channel.close();

        mReader = new PdfReader(byteArray);

        numPages = mReader.getNumberOfPages();
        bodyText = "";
    }

    public String parse()
    {
        int numThreads = 5;
        int offset = (numPages / numThreads) - 1;
        int currentFirstPage = 1;
        ParserThread[] threads = new ParserThread[numThreads];
        int forEnd = numThreads - 1;
        for (int i = 0; i < forEnd; i++)
        {
            threads[i] = new ParserThread(mReader, currentFirstPage, currentFirstPage + offset);
            threads[i].start();
            currentFirstPage += offset + 1;
        }
        threads[forEnd] = new ParserThread(mReader, currentFirstPage, numPages);
        threads[forEnd].start();

        try
        {
            long before = System.currentTimeMillis();
            for(int i = 0; i < numThreads; i++)
            threads[i].join();
            System.out.println(System.currentTimeMillis() - before);
        }
        catch(InterruptedException ie){ie.printStackTrace();}
        mReader.close(); 

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < numThreads;i++)
        {
            sb.append(threads[i].getText());
        }

        bodyText = sb.toString();
        if (bodyText != "")
            return bodyText;
        else
            return "error";
    }

    public static void main(final String args[]) throws IOException
    {
        for (int i = 0; i < args.length; i++) 
        {
            String text = new PDFParser(args[i]).parse();
            //      System.out.println(text);
        }
    }

}

class ParserThread extends Thread
{
    private PdfReader mReader;
    private int mFirstPage;
    private int mLastPage;
    private String text;

    ParserThread(PdfReader reader, int firstPage, int lastPage)
    {
        mReader = reader;
        mFirstPage = firstPage;
        mLastPage = lastPage;
        text = "";
    }

    @Override
    public void run()
    {
        StringBuilder sb = new StringBuilder();
        try
        {
            for (int i = mFirstPage; i <= mLastPage; i++)
            sb.append(PdfTextExtractor.getTextFromPage(mReader, i));
        }
        catch (IOException ioe)
        {
            ioe.printStackTrace();
        }
        text = sb.toString();
   }

   public String getText()
   {
       return text;
   }
}

0 ответов

Другие вопросы по тегам