Специальные символы неправильно преобразуются из pdf в текст

У меня есть набор файлов PDF, содержащих символы Центральной Европы, такие как č, Ď, Š и так далее. Я хочу преобразовать их в текст, и я пробовал pdftotext и PDFBox через Apache Tika, но всегда некоторые из них не преобразуются правильно.

Странно то, что один и тот же символ в одном и том же тексте в одних местах конвертируется правильно, а в других неправильно! Примером может служить этот pdf.

В случае pdftotext я использую следующие параметры:

pdftotext -nopgbrk -eol dos -enc UTF-8 070612.pdf

Мой код Tika выглядит так:

          String newname = f.getCanonicalPath().replace(".pdf", ".txt");
          OutputStreamWriter print = new OutputStreamWriter (new FileOutputStream(newname), Charset.forName("UTF-16"));
          String    fileString = "path\to\myfiles\"
          try{

              is = new FileInputStream(f);

              ContentHandler contenthandler = new BodyContentHandler(10*1024*1024);
              Metadata metadata = new Metadata();
              PDFParser pdfparser = new PDFParser();

              pdfparser.parse(is, contenthandler, metadata, new ParseContext());
              String outputString = contenthandler.toString();

              outputString = outputString.replace("\n", "\r\n");
              System.err.println("Writing now file "+newname);
              print.write(outputString);

          }catch (Exception e) {
              e.printStackTrace();
            }
            finally {
               if (is != null) is.close();
               print.close();
            }

Редактировать: Забыл упомянуть, что я столкнулся с той же проблемой при преобразовании в текст из Acrobat Reader XI.


person Yannis P.    schedule 24.06.2013    source источник


Ответы (1)


Помимо всего прочего, этот код будет использовать кодировку платформы по умолчанию:

PrintWriter print = new PrintWriter(newname);
print.print(outputString);
print.close();

Я предлагаю вам использовать OutputStreamWriter вместо FileOutputStream и указать UTF-8 в качестве кодировки (поскольку она может кодировать весь Unicode и обычно хорошо поддерживается).

Вы также должны закрыть модуль записи в блоке finally, и я бы, вероятно, отделил часть «чтения» от части «записи». (Я бы тоже не стал ловить Exception, но вдаваться в подробности обработки исключений немного выходит за рамки этого ответа.)

person Jon Skeet    schedule 24.06.2013
comment
Привет, Джон. Спасибо за ответ. Правда в том, что я спрятал некоторый код, который делал преобразование utf8 на уровне строки, т.е. перед записью в PrintWriter, но вы правы, OutputStreamWriter - лучшее решение. Тем не менее, все еще есть проблемы. Возможно, это связано с некоторыми проблемами с кодировкой PDF или около того, но я не эксперт по PDF. - person Yannis P.; 24.06.2013
comment
@YannisP.: Вы не должны ничего делать перед использованием записи - если вы это сделаете, вы почти наверняка сделаете что-то не так, потому что у обычного String нет никакой кодировки (или это всегда UTF-16, в зависимости от вашего POV ). Если вы в настоящее время перебираете строки, используя getBytes и конструктор String, немедленно прекратите это делать. - person Jon Skeet; 24.06.2013
comment
Хорошо, поэтому я перешел на OutputStreamWriter print = new OutputStreamWriter (new FileOutputStream(newname), Charset.forName("UTF-16"));, но проблемы остались. Я подозреваю, что это общая проблема с форматом pdf, потому что, среди прочего, конвертер Adobe Reader ведет себя так же. - person Yannis P.; 24.06.2013
comment
@YannisP.: Или, возможно, это проблема с PDF-файлом, который вы читаете? - person Jon Skeet; 24.06.2013
comment
Возможно, я видел это с несколькими pdf-файлами из того же источника. Что меня сводит с ума, так это то, что некоторые символы конвертируются правильно, а некоторые другие преобразуются, например, в. '}' - person Yannis P.; 24.06.2013