当自动检测解析器似乎工作正常时,为什么 Tika 的 ForkParser 会抛出 NoClassDefFoundError ?
我正在使用 apache Tika 1.0。使用 ForkParser,每当我解析 pdf 文件时,都会收到以下 NoClassDefFoundException:
java.lang.NoClassDefFoundError: org/apache/tika/fork/MemoryURLStreamHandler$Record
at org.apache.tika.fork.MemoryURLStreamHandler.createURL(MemoryURLStreamHandler.java:46)
at org.apache.tika.fork.ClassLoaderProxy.findResource(ClassLoaderProxy.java:73)
at java.lang.ClassLoader.getResource(ClassLoader.java:977)
at org.apache.log4j.helpers.Loader.getResource(Loader.java:96)
at org.apache.log4j.LogManager.<clinit>(LogManager.java:105)
at org.apache.log4j.Logger.getLogger(Logger.java:104)
at org.apache.commons.logging.impl.Log4JLogger.getLogger(Log4JLogger.java:289)
at org.apache.commons.logging.impl.Log4JLogger.<init>(Log4JLogger.java:109)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at org.apache.commons.logging.impl.LogFactoryImpl.createLogFromClass(LogFactoryImpl.java:1116)
at org.apache.commons.logging.impl.LogFactoryImpl.discoverLogImplementation(LogFactoryImpl.java:914)
at org.apache.commons.logging.impl.LogFactoryImpl.newInstance(LogFactoryImpl.java:604)
at org.apache.commons.logging.impl.LogFactoryImpl.getInstance(LogFactoryImpl.java:336)
at org.apache.commons.logging.impl.LogFactoryImpl.getInstance(LogFactoryImpl.java:310)
at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:685)
at org.apache.pdfbox.pdfparser.BaseParser.<clinit>(BaseParser.java:58)
at org.apache.pdfbox.pdmodel.PDDocument.load(PDDocument.java:1087)
at org.apache.pdfbox.pdmodel.PDDocument.load(PDDocument.java:1053)
at org.apache.tika.parser.pdf.PDFParser.parse(PDFParser.java:80)
at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:242)
at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:242)
at org.apache.tika.parser.AutoDetectParser.parse(AutoDetectParser.java:120)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.tika.fork.ForkServer.call(ForkServer.java:136)
at org.apache.tika.fork.ForkServer.processRequests(ForkServer.java:116)
at org.apache.tika.fork.ForkServer.main(ForkServer.java:64)
检查 jar 显示 MemoryURLStreamHandler$Record 存在于 tika-core jar 文件中。当我使用 AutoDetectParser 而不是 ForkParser 时,我能够毫无问题地从文件中提取元数据,但需要能够限制 Tika 内存使用,因此需要使用 ForkParser。如何使用 Tika 的 ForkParser 进行 pdf 解析?
下面是我进行解析的代码片段:
public static FileAnalysis analyze(File f) throws java.io.FileNotFoundException{
FileInputStream fis = null;
ToXMLContentHandler contentHandler = new ToXMLContentHandler();
Metadata metadata = new Metadata();
ParseContext context = new ParseContext();
ForkParser parser = new ForkParser();
parser.setJavaCommand(props.getProperty("forkJavaCommand", "java") + " " +
props.getProperty("forkJavaMemory", "-Xmx64m"));
parser.setPoolSize(1);
fis = new FileInputStream(f);
try {
parser.parse(fis, contentHandler, metadata, context);
} catch (Throwable e) {
logger.error("Exception while analyzing file\n" +
"CAUTION: metadata may still have useful content in it!\n" +
"Exception:\n" + e, e);
}
编辑 #1
我使用“-f”选项测试了 Tika 1.0 和 Tika 0.10 CLI 应用程序,并在使用 SoyLatte java 6 端口时收到 IOException(管道损坏)适用于 Mac OS-X。该端口仅在我的开发计算机上运行,因此我使用“-f”开关在 Linux 测试计算机上运行 CLI 应用程序(1.0 和 0.10),如下所示
java -jar tika-app-1.0.jar -f /path/to/my/file.pdf
我不再收到异常,但我也没有得到任何输出。我发现这很奇怪,但认为它可能仍然有效,只是没有产生任何输出(我猜永远是一个乐观主义者)。
我在 Mac OS-X 终端中取消了所有环境变量的设置,并尝试使用 OS-X 内置的 java 6 运行 Tika CLI。我得到了与 Linux 测试机上相同的结果,打印了一些换行符,但是没有别的。我尝试使用 jpg 文件而不是 pdf 文件,tika 应用程序打印出带有广告元数据的 xhtml 文档!接下来我尝试了 docx 文件,但与 pdf 一样,不打印任何内容。
编辑 #2
我编写了一个小型测试 java 程序,并将其放置在应用程序的上下文之外,以便它在新的环境中运行。
import java.io.File;
import java.io.FileInputStream;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.fork.ForkParser;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.sax.ToXMLContentHandler;
import org.apache.tika.Tika;
public class ForkParserTest {
public static void main(String[] args) {
if (args.length != 1) {
System.out.println("must be passed the file to be parsed as the first argument");
return;
}
try {
File f = new File(args[0]);
FileInputStream fis = null;
ToXMLContentHandler contentHandler = new ToXMLContentHandler();
Metadata metadata = new Metadata();
ParseContext context = new ParseContext();
ForkParser parser = new ForkParser();
fis = new FileInputStream(f);
parser.parse(fis, contentHandler, metadata, context);
System.out.println(contentHandler.toString());
} catch (Exception e) {
System.out.println("Exception caught in main");
e.printStackTrace();
}
return;
}
}
我像这样编译它
javac -cp /path/to/tika-app-1.0.jar ForkParserTest.java
并像这样运行
java -cp /path/to/tika-app-1.0 .jar:${PWD} ForkParserTest /path/to/file.pdf
并使用 jpeg 对其进行了测试。它的执行方式与 Tika CLI 应用程序完全相同,它打印 jpg 的 XHTML 文档,但不打印 pdf 或 docx 文件的任何内容。
如果有人知道如何解决这个问题,请告诉我!另外,如果您对 pdf 文件或 docx 文件运行此测试并实际获得要打印的结果,也请告诉我您是如何做到的。
谢谢!
我对在 stackoverflow 上发帖也相当陌生,如果这完全是 tl;dr,欢迎提供反馈,请给我关于如何使其更简洁的建议。
I'm using apache Tika 1.0. Using ForkParser, whenever I parse pdf files, I get the following NoClassDefFoundException:
java.lang.NoClassDefFoundError: org/apache/tika/fork/MemoryURLStreamHandler$Record
at org.apache.tika.fork.MemoryURLStreamHandler.createURL(MemoryURLStreamHandler.java:46)
at org.apache.tika.fork.ClassLoaderProxy.findResource(ClassLoaderProxy.java:73)
at java.lang.ClassLoader.getResource(ClassLoader.java:977)
at org.apache.log4j.helpers.Loader.getResource(Loader.java:96)
at org.apache.log4j.LogManager.<clinit>(LogManager.java:105)
at org.apache.log4j.Logger.getLogger(Logger.java:104)
at org.apache.commons.logging.impl.Log4JLogger.getLogger(Log4JLogger.java:289)
at org.apache.commons.logging.impl.Log4JLogger.<init>(Log4JLogger.java:109)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at org.apache.commons.logging.impl.LogFactoryImpl.createLogFromClass(LogFactoryImpl.java:1116)
at org.apache.commons.logging.impl.LogFactoryImpl.discoverLogImplementation(LogFactoryImpl.java:914)
at org.apache.commons.logging.impl.LogFactoryImpl.newInstance(LogFactoryImpl.java:604)
at org.apache.commons.logging.impl.LogFactoryImpl.getInstance(LogFactoryImpl.java:336)
at org.apache.commons.logging.impl.LogFactoryImpl.getInstance(LogFactoryImpl.java:310)
at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:685)
at org.apache.pdfbox.pdfparser.BaseParser.<clinit>(BaseParser.java:58)
at org.apache.pdfbox.pdmodel.PDDocument.load(PDDocument.java:1087)
at org.apache.pdfbox.pdmodel.PDDocument.load(PDDocument.java:1053)
at org.apache.tika.parser.pdf.PDFParser.parse(PDFParser.java:80)
at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:242)
at org.apache.tika.parser.CompositeParser.parse(CompositeParser.java:242)
at org.apache.tika.parser.AutoDetectParser.parse(AutoDetectParser.java:120)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.tika.fork.ForkServer.call(ForkServer.java:136)
at org.apache.tika.fork.ForkServer.processRequests(ForkServer.java:116)
at org.apache.tika.fork.ForkServer.main(ForkServer.java:64)
Inspecting the jar shows that MemoryURLStreamHandler$Record exists in the tika-core jar file. When I use the AutoDetectParser instead of ForkParser, I am able to extract metadata from the files without any problems, but need to be able to constrain Tika memory usage, so am required to use ForkParser. How can I get pdf parsing to work with Tika's ForkParser?
Here's a snippet of code up to where I do the parse:
public static FileAnalysis analyze(File f) throws java.io.FileNotFoundException{
FileInputStream fis = null;
ToXMLContentHandler contentHandler = new ToXMLContentHandler();
Metadata metadata = new Metadata();
ParseContext context = new ParseContext();
ForkParser parser = new ForkParser();
parser.setJavaCommand(props.getProperty("forkJavaCommand", "java") + " " +
props.getProperty("forkJavaMemory", "-Xmx64m"));
parser.setPoolSize(1);
fis = new FileInputStream(f);
try {
parser.parse(fis, contentHandler, metadata, context);
} catch (Throwable e) {
logger.error("Exception while analyzing file\n" +
"CAUTION: metadata may still have useful content in it!\n" +
"Exception:\n" + e, e);
}
Edit #1
I tested both the Tika 1.0 and Tika 0.10 CLI app with the “-f” option and was receiving an IOException (Broken Pipe) while using the SoyLatte java 6 port for Mac OS-X. The port is only being run on my development machine, so I ran the CLI app (both 1.0 and 0.10) on a linux testing machine with the “-f” switch as follows
java -jar tika-app-1.0.jar -f /path/to/my/file.pdf
I was no longer receiving an exception, but I was also not getting any output. I found this odd, but thought it may still be working, just not producing any output (forever an optimist, I guess).
I unset all my environment variables in my Mac OS-X terminal and tried running the Tika CLI just as above with OS-X’s built in java 6. I got the same result as on the linux test machine, a few newlines get printed, but nothing else. I tried a jpg file instead of the pdf file and the tika app printed out the xhtml document with the metadata as advertised! I tried a docx file next, but like pdfs, does not print anything.
Edit #2
I wrote a small test java program and placed it outside of the context of our application so that it’s running in a fresh environment.
import java.io.File;
import java.io.FileInputStream;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.fork.ForkParser;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.sax.ToXMLContentHandler;
import org.apache.tika.Tika;
public class ForkParserTest {
public static void main(String[] args) {
if (args.length != 1) {
System.out.println("must be passed the file to be parsed as the first argument");
return;
}
try {
File f = new File(args[0]);
FileInputStream fis = null;
ToXMLContentHandler contentHandler = new ToXMLContentHandler();
Metadata metadata = new Metadata();
ParseContext context = new ParseContext();
ForkParser parser = new ForkParser();
fis = new FileInputStream(f);
parser.parse(fis, contentHandler, metadata, context);
System.out.println(contentHandler.toString());
} catch (Exception e) {
System.out.println("Exception caught in main");
e.printStackTrace();
}
return;
}
}
I compiled it like so
javac -cp /path/to/tika-app-1.0.jar ForkParserTest.java
and ran like so
java -cp /path/to/tika-app-1.0.jar:${PWD} ForkParserTest /path/to/file.pdf
and tested it with a jpeg as well. It performs exactly like the Tika CLI app where it prints the XHTML document for the jpg but prints nothing for pdf or docx files.
If anyone knows how to resolve this problem, please let me know! Also, if you run this test on pdf files or docx files and actually get results to print, please also let me know how you did it.
Thanks!
I'm also fairly new to posting on stackoverflow, if this is totally tl;dr, feedback is appreciated, give me suggestions for how to make this more concise.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论