我有一个Java 8程序,它从用户提供的节点遍历目录树,搜索与用户提供的文件名模式列表匹配的文件。
可以使用可选的用户提供的String
过滤匹配文件列表以进行查找。代码使用解析的最终结果检查此字符串。当在树步行中找到大文件时,这非常糟糕。
但无论如何它还不错。一旦找到要查找的字符串,我们就会浪费时间来解析文件的其余部分。
找到匹配后,有没有办法让tika停止解析文件?
修改的
该程序所基于的代码:
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
会返回BodyContentHandler
handler
文件中的所有文字。解析器的实现者没有可用的循环。没有我知道的;因此问题。
编辑2
我想我真正想知道的是,是否存在仅从文件而不是全部读取n
个字符的tika方法。然后我可以在它周围粘上一个循环并在找到搜索字符串时退出。
答案 0 :(得分: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 已添加到tika-example包中:https://github.com/apache/tika/blob/trunk/tika-example/src/main/java/org/apache/tika/example/InterruptableParsingExample.java