java -PDFBox, как извлечь текст из документов без сохранения в массиве? - PullRequest
0 голосов
/ 29 ноября 2018

Я использую PDFBox для извлечения текста из документов PDF.Затем, после извлечения, я вставлю этот текст в таблицу в MySQL.

Код:

PDDocument document = PDDocument.load(new File(path1));

if (!document.isEncrypted()) {
    PDFTextStripper tStripper = new PDFTextStripper();
    String pdfFileInText = tStripper.getText(document);
    String lines[] = pdfFileInText.split("\\r?\\n");
    for (String line : lines) {
        String[] words = line.split(" ");

        String sql="insert IGNORE into  test.indextable values (?,?);";

        preparedStatement = con1.prepareStatement(sql);
        int i=0;
        for (String word : words) {
            // check if one or more special characters at end of string then remove OR
            // check special characters in beginning of the string then remove
            // insert every word directly to table db
            word=word.replaceAll("([\\W]+$)|(^[\\W]+)", "");
            preparedStatement.setString(1, path1);
            preparedStatement.setString(2, word);

            /* preparedStatement.executeUpdate();
            System.out.print("Add ");*/

            preparedStatement.addBatch();

            i++;
            if (i % 1000 == 0) {
                preparedStatement.executeBatch();

                System.out.print("Add Thousand");
            }
        }

        if (i > 0) {
            preparedStatement.executeBatch();

            System.out.print("Add Remaining");
        }
    }
}

Код работает нормально, но, как вы можете видеть, если документ большой и содержит около 10 миллионов слов, lines[] ничего не сделаетсправедливость и бросит out of memory exception.

Я не могу придумать решение этого.Есть ли способ, которым я мог бы просто извлечь и вставить слова непосредственно в БД, или это невозможно?

РЕДАКТИРОВАНИЕ:

Это то, что я сделал:

processText метод:

public void processText(String text) throws SQLException {

    String lines[] = text.split("\\r?\\n");
    for (String line : lines) {
        String[] words = line.split(" ");


        String sql="insert IGNORE into  test.indextable values (?,?);";


        preparedStatement = con1.prepareStatement(sql);
        int i=0;
        for (String word : words) {

            // check if one or more special characters at end of string then remove OR
            // check special characters in beginning of the string then remove
            // insert every word directly to table db
            word=word.replaceAll("([\\W]+$)|(^[\\W]+)", "");
            preparedStatement.setString(1, path1);
            preparedStatement.setString(2, word);



            preparedStatement.addBatch();

            i++;
            if (i % 1000 == 0) {
                preparedStatement.executeBatch();

                System.out.print("Add Thousand");
            }




        }




        if (i > 0) {
            preparedStatement.executeBatch();

            System.out.print("Add Remaining");

        }

    }
    preparedStatement.close();
    System.out.println("Successfully commited changes to the database!");

}

индексный метод (вызов вышеуказанного метода):

public void index() throws Exception {
       // Connection con1 = con.connect();
        try {

            // Connection con1=con.connect();
           // Connection con1 = con.connect();
            Statement statement = con1.createStatement();

            ResultSet rs = statement.executeQuery("select * from filequeue where Status='Active' LIMIT 5");


            while (rs.next()) {
                // get the filepath of the PDF document
                 path1 = rs.getString(2);
               int getNum = rs.getInt(1);
                // while running the process, update status : Processing
                //updateProcess_DB(getNum);
                Statement test = con1.createStatement();
                test.executeUpdate("update filequeue SET STATUS ='Processing' where UniqueID="+getNum);



                try {
                    // call the index function


                    /*Indexing process = new Indexing();

                    process.index(path1);*/

                    PDDocument document = PDDocument.load(new File(path1));

                    if (!document.isEncrypted()) {

                        PDFTextStripper tStripper = new PDFTextStripper();
                        for(int p=1; p<=document.getNumberOfPages();++p) {
                            tStripper.setStartPage(p);
                            tStripper.setEndPage(p);
                            String pdfFileInText = tStripper.getText(document);
                            processText(pdfFileInText);
                        }


                        }

1 Ответ

0 голосов
/ 29 ноября 2018

Ваш текущий код использует строку pdfFileInText, которая получается из tStripper.getText(document); и получает весь документ сразу.Сначала выполните рефакторинг всего, что вы делаете с этой строкой (она начинается с pdfFileInText.split) в отдельном методе, например, processText.Затем измените свой код следующим образом:

PDFTextStripper tStripper = new PDFTextStripper();
for (int p = 1; p <= document.getNumberOfPages(); ++p)
{
    stripper.setStartPage(p); // 1-based
    stripper.setEndPage(p); // 1-based
    String pdfFileInText = tStripper.getText(document);
    processText(pdfFileInText);
}

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

...