2015-05-04 2 views
0

Я использую Tika jar для извлечения метаданных из файлов Microsoft Word doc, но в случае, когда Tika сталкивается с проблемой, мое спасение не улавливает ошибку, вместо этого скрипты завершаются. Я на Windows 7 с MRI Ruby 1.9.3 Я мог бы адаптировать файл doc, но я хочу избежать этой проблемы с будущими файлами. Как я могу захватить эту ошибку?запустить внешнюю программу в Ruby IO.popen: аварийное восстановление не работает

JARPATH = "jar/tika-app-1.6.jar" 

def metadata 
    return @metadata if defined? @metadata 
    switch = '-m -j' 
    begin 
     command = %Q{java -Djava.awt.headless=true -jar #{JARPATH} #{switch} "#{@path}"} 
     output = IO.popen(command+" 2>&1") do |io| 
     io.read 
     end 
     if output.respond_to?(:to_str) 
     @metadata = JSON.parse(output) 
     else 
     @metadata = nil 
     end 
    rescue => e 
     puts e 
     puts e.backtrace 
    end 
    end 

Это выход я получаю

c:/Ruby193/lib/ruby/gems/1.9.1/gems/json-1.8.2/lib/json/common.rb:155:in `parse': 757: unexpected token at 'Exception in thread "main" org.apache.tika.exception.TikaException: TIKA-198: Illegal IOExce 
ption from [email protected] (JSON::ParserError) 
     at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:250) 
     at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:244) 
     at org.apache.tika.parser.AutoDetectParser.parse(AutoDetectParser.java:121) 
     at org.apache.tika.cli.TikaCLI$OutputType.process(TikaCLI.java:143) 
     at org.apache.tika.cli.TikaCLI.process(TikaCLI.java:422) 
     at org.apache.tika.cli.TikaCLI.main(TikaCLI.java:113) 
Caused by: java.io.IOException: Invalid header signature; read 0x04090000002DA5DB, expected 0xE11AB1A1E011CFD0 - Your file appears not to be a valid OLE2 document 
     at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:140) 
     at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:115) 
     at org.apache.poi.poifs.filesystem.NPOIFSFileSystem.<init>(NPOIFSFileSystem.java:204) 
     at org.apache.poi.poifs.filesystem.NPOIFSFileSystem.<init>(NPOIFSFileSystem.java:163) 
     at org.apache.tika.parser.microsoft.OfficeParser.parse(OfficeParser.java:162) 
     at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:244) 
     ... 5 more 
' 
     from c:/Ruby193/lib/ruby/gems/1.9.1/gems/json-1.8.2/lib/json/common.rb:155:in `parse' 
     from C:/Users/.../tika.rb:37:in `metadata' 
     from C:/Users/.../index_helpers.rb:55:in `index_doc' 
     from index.rb:39:in `block in <main>' 
     from index.rb:20:in `each' 
     from index.rb:20:in `each_with_index' 
     from index.rb:20:in `<main>' 
+0

Почему бы не использовать [Сетевой сервер Tika] (http://wiki.apache.org/tika/TikaJAXRS) вместо того, чтобы создавать новую JVM при каждом вызове приложения? Вы разместите свой контент по сети и вернете метаданные или ошибку, красиво изолированную от вашего рубина. – Gagravarr

+0

Кроме того, конкретная ошибка в вашей stacktrace исправлена ​​в последней версии Apache Tika, есть ли причина, Повторное использование старого? – Gagravarr

+0

@ Gagravarr, малый бизнес здесь, необходимо свести к минимуму количество серверных процессов, которые работают, только работающий с веб-сервером IIS и Tomcat, которые я бы не использовал. Тика была установлена ​​с драгоценным камнем Йоми, который я не хотел использовать, но заваривал свой класс, чтобы взаимодействовать с Тикой. Tika дает ту же ошибку при запуске из командной строки, я взгляну на эту новую версию. – peter

ответ

2

После Вашего звонка, чтобы IO.popen вы передаете выход из программы детского до JSON.parse, независимо от того, является ли он действительным. Исключением, которое вы видите, является парсер json, пытающийся проанализировать метод исключения Java, который фиксируется, потому что вы перенаправляете stderr с помощью 2>&1.

Перед продолжением необходимо убедиться, что дочерний процесс успешно завершен. Самый простой способ - это, вероятно, использовать специальную переменную $?, которая указывает статус последнего исполняемого дочернего процесса после вызова popen. Эта переменная является экземпляром, если Process::Status. Вы могли бы сделать что-то вроде этого:

output = IO.popen(command+" 2>&1") do |io| 
    io.read 
end 

unless $?.success? 
    # Handle the error however you feel is best, e.g. 
    puts "Tika had an error, the message was:\n#{output}" 
    raise "Tika error" 
end 

Для большего контроля можно посмотреть на Open3 module в стандартной библиотеке. Поскольку Tika - это Java-программа, другой возможностью может быть изучение JRuby и вызов ее напрямую.

Смежные вопросы