Не удается прочитать отдельную страницу, используя PDFTextStripper с несколькими потоками - PullRequest
0 голосов
/ 01 ноября 2019

Я могу создать 10 тем. Но проблема в том, когда я пытаюсь получить доступ к отдельной странице, используя эти потоки в параллельном стиле. Я попытался поместить частный статический экземпляр PDFTextStripper в синхронизированный блок, а также. Тем не менее я получаю исключение ниже:

COSStream был закрыт и не может быть прочитан. Возможно, его закрывающий PDDocument был закрыт?

пытается напечатать первое слово с каждой страницы для первых 10 страниц, но это не работает. Это мой первый эксперимент с многопоточностью и чтением PDF. Любая помощь будет принята с благодарностью.

public class ReadPDFFile extends Thread implements FileInstance {
    private static String fileLocation;
    private static String fileNameIV;
    private static String userInput;
    private static int userConfidence;
    private static int totalPages;
    private static ConcurrentHashMap<Integer, List<String>> map = null;
    private Iterator<PDDocument> iteratorForThisDoc;
    private PDFTextStripperByArea text;
    private static PDFTextStripper pdfStrip = null;
    private static PDFParser pdParser = null;
    private Splitter splitter;
    private static int counter=0;
    private StringWriter writer;
    private static  ReentrantLock counterLock = new ReentrantLock(true);
    private static PDDocument doc;
    private static PDDocument doc2;
    private static boolean flag = false;
    List<PDDocument> listOfPages;

    ReadPDFFile(String filePath, String fileName, String userSearch, int confidence) throws FileNotFoundException{
        fileLocation= filePath;
        fileNameIV =  fileName;
        userInput= userSearch;
        userConfidence = confidence;
        System.out.println("object created");
    }

    @Override
    public void createFileInstance(String filePath, String fileName) {
        List<String> list = new ArrayList<String>();
        map = new ConcurrentHashMap<Integer, List<String>>();
        try(PDDocument document = PDDocument.load(new File(filePath))){
            doc = document;
            pdfStrip = new PDFTextStripper();
            this.splitter = new Splitter();
            text = new PDFTextStripperByArea();
            document.getClass();
            if(!document.isEncrypted()) {
                totalPages = document.getNumberOfPages();
                System.out.println("Number of pages in this book "+totalPages);
                listOfPages = splitter.split(document);
                iteratorForThisDoc = listOfPages.iterator();
            }
            this.createThreads();
            /*
             * for(int i=0;i<1759;i++) { readThisPage(i, pdfStrip); } flag= true;
             */
        }
        catch(IOException ie) {
            ie.printStackTrace();
        }
    }

    public void createThreads() {
        counter=1;
        for(int i=0;i<=9;i++) {
            ReadPDFFile pdf = new ReadPDFFile();
            pdf.setName("Reader"+i);
            pdf.start();
        }
    }

    public void run() {
        try {
            while(counter < 10){
                int pgNum= pageCounterReentrant();
                readThisPage(pgNum, pdfStrip);
            }
            doc.close();
        }catch(Exception e) {
        }   
        flag= true;
    }

    public static int getCounter() {
        counter=  counter+1;
        return counter;
    }

    public static int pageCounterReentrant() {
        counterLock.lock();
        try {
            counter =  getCounter();
        } finally {
            counterLock.unlock();
        }
        return counter;
    }

    public static void readThisPage(int pageNum, PDFTextStripper ts) {
        counter++;
        System.out.println(Thread.currentThread().getName()+" reading page: "+pageNum+", counter: "+counter);

        synchronized(ts){
            String currentpageContent= new String();
            try {
                ts.setStartPage(pageNum);
                ts.setEndPage(pageNum);
                System.out.println("-->"+ts.getPageEnd());
                currentpageContent = ts.getText(doc);
                currentpageContent = currentpageContent.substring(0, 10);
                System.out.println("\n\n "+currentpageContent);
            }

        /*
         * further operations on currentpageContent here
         */

            catch(IOException io) {
                io.printStackTrace();
            }finally {
            }
        } 
    }

    public static void printFinalResult(ConcurrentHashMap<Integer, List<String>> map) {
        /*
         * simply display content of ConcurrentHashMap
         */
    }

    public static void main(String[] args) throws FileNotFoundException {
        Scanner sc = new Scanner(System.in); 
        System.out.println("Search Word");
        userInput = sc.nextLine(); 
        System.out.println("Confidence"); 
        userConfidence = sc.nextInt(); 
        ReadPDFFile pef = new ReadPDFFile("file path", "file name",userInput, userConfidence);
        pef.createFileInstance("file path ","file name");
        if(flag==true)
            printFinalResult(map);
     }
}

Если я читаю каждую страницу в цикле for последовательно, используя одну нить, тогда она может печатать содержимое, но не с многопоточностью. Вы можете видеть, что код прокомментирован в void createFileInstance (), после this.createThreads ();Я хочу получить строковое содержимое каждой PDF-страницы в отдельности, используя потоки, а затем выполнить операцию над нейУ меня есть логика собирать каждый токен слова в List, но прежде чем двигаться дальше, мне нужно решить эту проблему.

1 Ответ

0 голосов
/ 02 ноября 2019

Ваш код выглядит следующим образом:

try(PDDocument document = PDDocument.load(new File(filePath))){
    doc = document;
    ....
    this.createThreads();
} // document gets closed here
...
//threads that do text extraction still running here (and using a closed object)

Эти темы используют документ для извлечения текста (ts.getText(doc)). Однако в это время объект PDDocument уже закрыт из-за использования try-with-resources , и его потоки также закрыты. Таким образом, сообщение об ошибке «Возможно, включающий PDDocument был закрыт?».

Вы должны создать поток перед закрытием документа и дождаться завершения всех потоков, прежде чем закрывать его.

I 'не советую использовать многопоточность на одном PDDocument, см. PDFBOX-4559 . Вы можете создать несколько PDDocuments, а затем извлечь их или вообще не делать. В PDFBox извлечение текста работает довольно быстро (по сравнению с рендерингом).

...