2015-08-11 4 views
0

У меня есть программа Java 8, которая перемещается по дереву каталогов из предоставленного пользователем узла, ища файлы, соответствующие списку пользовательских шаблонов имен файлов.Есть ли способ заставить tika останавливать синтаксический анализ файла после того, как совпадение найдено?

Список сопоставленных файлов можно отфильтровать с помощью дополнительного String для поиска. Код проверяет эту строку, используя итоговый результат . Это очень плохо, когда огромные файлы находятся вдоль прогулки по дереву.

Но все равно. Как только найденная строка найдена, мы теряем время, анализируя остальную часть файла.

Есть ли способ, чтобы tika останавливал разбор файла после того, как совпадение найдено?

EDIT

код, что программа основана на:

package org.apache.tika.example; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.net.MalformedURLException; 
import org.apache.tika.exception.TikaException; 
import org.apache.tika.metadata.Metadata; 
import org.apache.tika.mime.MimeTypeException; 
import org.apache.tika.parser.AutoDetectParser; 
import org.apache.tika.sax.BodyContentHandler; 
import org.xml.sax.SAXException; 

public class ParsingExample { 

    public static boolean contains(File file, String s) throws MalformedURLException, 
        IOException, MimeTypeException, SAXException, TikaException 
    { 
    InputStream   stream = new FileInputStream(file); 
    AutoDetectParser parser = new AutoDetectParser(); 
    BodyContentHandler handler = new BodyContentHandler(-1); 
    Metadata   metadata = new Metadata(); 
    try 
    { 
     parser.parse(stream, handler, metadata); 
     return handler.toString().toLowerCase().contains(s.toLowerCase()); 
    } 
    catch (IOException | SAXException | TikaException e) 
    { 
     System.out.println(file + ": " + e + "\n"); 
     return false; 
    } 
    } 
    public static void main(String[] args) 
    { 
     try 
     { 
     System.out.println("File " + filename + " contains <" + searchString + "> : " + contains(new File(filename), searchString)); 
     } 
     catch (IOException | SAXException | TikaException ex) 
     { 
     System.out.println("Error: " + ex); 
     } 
    } 

    static String parseExample = ":("; 
    static String searchString = "test"; 
    static String filename = "test.doc"; 
} 

Parser.parser возвращает весь текст в файле для BodyContentHandlerhandler. Для разработчика синтаксического анализа нет петли. Нет, что я знаю; следовательно, вопрос.

EDIT 2

То, что я действительно хочу знать, я думаю, есть ли там метод ТИКА, который читает только n символы из файла, а не все. Тогда я мог бы придерживаться цикла вокруг него и выйти, если будет найдена строка поиска.

+1

вы можете предоставить некоторый код? – yelliver

+0

У вашего кода установлен флаг, который завершает цикл? Выбросить исключение? – Gagravarr

+0

Обратитесь к * EDIT * в OQ. – DSlomer64

ответ

1

Вы можете перемещать соответствующий запрос часть в свой собственный ContentHandler реализации (вы можете взять DefaultHandler как основание) с повторной сборкой текста из частей, переданных ContentHander#characters(char[],int,int) и прервать разбор, бросая исключение там после того, как совпадение.

Это определенно не очень хорошее решение, но оно должно прекратить разбор.

UPD Пример кода:

public class InterruptableParsingExample { 
    private Tika tika = new Tika(); // for default autodetect parser 

    public boolean findInFile(String query, File file) { 
     Metadata metadata = new Metadata(); 
     InterruptingContentHandler handler = new InterruptingContentHandler(query); 
     ParseContext context = new ParseContext(); 
     context.set(Parser.class, tika.getParser()); 

     try (InputStream is = new BufferedInputStream(new FileInputStream(file))) { 
      tika.getParser().parse(is, handler, metadata, context); 
     } catch (QueryMatchedException e) { 
      return true; 
     } catch (SAXException | TikaException | IOException e) { 
      // something went wrong with parsing... 
      e.printStackTrace(); 
     } 
     return false; 
    } 
} 

class QueryMatchedException extends SAXException {} 

class InterruptingContentHandler extends DefaultHandler { 
    private String query; 
    private StringBuilder sb = new StringBuilder(); 

    InterruptingContentHandler(String query) { 
     this.query = query; 
    } 

    @Override 
    public void characters(char[] ch, int start, int length) throws SAXException { 
     sb.append(new String(ch, start, length).toLowerCase()); 

     if (sb.toString().contains(query)) 
      throw new QueryMatchedException(); // interrupt parsing by throwing SaxException 

     if (sb.length() > 2 * query.length()) 
      sb.delete(0, sb.length() - query.length()); // keep tail with query.length() chars 
    } 
} 

UPD2 Добавлен ТИКА-пример пакета: https://github.com/apache/tika/blob/trunk/tika-example/src/main/java/org/apache/tika/example/InterruptableParsingExample.java

+0

@ Konstantin - Я ценю ответ, но мне нужно будет узнать больше о том, как и где настраивать код. Это мое первое предприятие в Tika и синтаксический анализ, и я подделал его (довольно хорошо). – DSlomer64

+0

@ DSlomer64, обновленный ответ с примером кода. Управляющий поток инвертирован (нормальный поток содержит исключение бросания), но аналогичный шаблон используется в «WriteOutContentHandler» Tika. –