Apache Tika 教程 Apache Tika 是一个内容分析工具包用于检测和提取文档中的元数据和文本内容。它支持超过1000种文件格式。1. 核心特性格式检测自动识别文件类型MIME内容提取提取纯文本内容元数据提取获取作者、创建日期等信息语言检测识别文档语言2. 快速开始Maven 依赖dependency groupIdorg.apache.tika/groupId artifactIdtika-core/artifactId version2.9.1/version /dependency dependency groupIdorg.apache.tika/groupId artifactIdtika-parsers-standard-package/artifactId version2.9.1/version /dependency基础用法import org.apache.tika.Tika; import java.io.File; import java.io.InputStream; // 最简单的方式 Tika tika new Tika(); String text tika.parseToString(new File(document.pdf)); System.out.println(text);3. 主要使用方式方式一Tika API推荐新手Tika tika new Tika(); // 文件类型检测 String mimeType tika.detect(new File(test.pdf)); // 解析文件 String content tika.parseToString(new File(test.docx)); // 解析流 try (InputStream is new FileInputStream(test.pptx)) { String content tika.parseToString(is); }方式二Parser API更精细控制import org.apache.tika.parser.AutoDetectParser; import org.apache.tika.metadata.Metadata; import org.apache.tika.sax.BodyContentHandler; AutoDetectParser parser new AutoDetectParser(); BodyContentHandler handler new BodyContentHandler(); Metadata metadata new Metadata(); try (InputStream stream new FileInputStream(document.pdf)) { parser.parse(stream, handler, metadata); // 获取文本 String text handler.toString(); // 获取元数据 String author metadata.get(Author); String date metadata.get(Creation-Date); }方式三RecursiveParser递归嵌入文件RecursiveParserWrapper wrapper new RecursiveParserWrapper( new AutoDetectParser() ); try (InputStream stream new FileInputStream(embedded.doc)) { wrapper.parse(stream, new BodyContentHandler(), new Metadata()); for (RecursiveParserWrapperHandler.MetadataWithContent mwc : wrapper.getMetadataList()) { System.out.println(File: mwc.getMetadata().get(Metadata.RESOURCE_NAME_KEY)); System.out.println(Content: mwc.getContentHandler().toString()); } }4. 常见文件格式支持格式扩展名支持程度PDF.pdf完整Word.doc, .docx完整Excel.xls, .xlsx完整PowerPoint.ppt, .pptx完整HTML/XML.html, .xml完整图片.jpg, .png, .gif文本元数据邮件.eml, .msg完整RTF.rtf完整TXT.txt完整5. 配置选项设置最大字符串长度// 默认100k字符 BodyContentHandler handler new BodyContentHandler(500000);自定义配置import org.apache.tika.config.TikaConfig; TikaConfig config new TikaConfig(); Tika tika new Tika(config); // 或使用自定义配置文件 TikaConfig config new TikaConfig(my-tika-config.xml);排除特定解析器Parsers parsers new Parsers(); SetMediaType excluded Set.of( MediaType.APPLICATION_ZIP, MediaType.APPLICATION_PDF ); AutoDetectParser parser new AutoDetectParser( parsers.getParsers(excluded) );6. 高级功能语言检测import org.apache.tika.language.LanguageIdentifier; String text This is an English sentence.; LanguageIdentifier identifier new LanguageIdentifier(text); String language identifier.getLanguage(); // en提取特定元数据Metadata metadata new Metadata(); // 常用元数据字段 metadata.names().forEach(name - { System.out.println(name : metadata.get(name)); }); // 标准字段 metadata.get(Metadata.AUTHOR); metadata.get(Metadata.CREATION_DATE); metadata.get(Metadata.TITLE);嵌入式内容处理EmbeddedDocumentExtractor extractor new EmbeddedDocumentExtractor() { Override public boolean shouldParseEmbedded(Metadata metadata) { return true; } Override public void parseEmbedded(InputStream stream, ContentHandler handler, Metadata metadata, boolean outputHtml) { // 处理嵌入式文件 } };7. 命令行工具Tika 提供了命令行版本# 下载 tika-app.jar wget https://archive.apache.org/dist/tika/2.9.1/tika-app-2.9.1.jar # 提取文本 java -jar tika-app-2.9.1.jar --text document.pdf # 检测MIME类型 java -jar tika-app-2.9.1.jar --detect file.pdf # 提取元数据 java -jar tika-app-2.9.1.jar --metadata document.docx # 列出支持的类型 java -jar tika-app-2.9.1.jar --list-supported-types # JSON输出 java -jar tika-app-2.9.1.jar --json document.pdf8. 性能优化复用解析器实例// 正确做法 - 单例 private static final AutoDetectParser PARSER new AutoDetectParser(); // 错误做法 - 每次新建 // AutoDetectParser parser new AutoDetectParser(); // 消耗资源使用ParseContext缓存ParseContext context new ParseContext(); context.set(Parser.class, PARSER); // 复用context parser.parse(stream, handler, metadata, context);配置内存限制TikaConfig config TikaConfig.getDefaultConfig(); // 修改配置限制解析时间和内存9. 常见问题解决中文乱码// 确保使用正确的字符编码 BodyContentHandler handler new BodyContentHandler(-1); // 手动设置编码 String content new String(text.getBytes(ISO-8859-1), UTF-8);大文件处理// 使用流式处理避免全部加载到内存 try (InputStream stream new FileInputStream(large.pdf)) { // 限制解析内容大小 BodyContentHandler handler new BodyContentHandler(1024 * 1024); parser.parse(stream, handler, metadata); }异常处理import org.apache.tika.exception.TikaException; import org.xml.sax.SAXException; try { String content tika.parseToString(file); } catch (TikaException e) { // Tika 特定错误如无法解析 System.err.println(Tika error: e.getMessage()); } catch (IOException e) { // 文件读写错误 System.err.println(IO error: e.getMessage()); } catch (SAXException e) { // XML 解析错误 System.err.println(SAX error: e.getMessage()); }10. 完整示例文档索引工具import org.apache.tika.Tika; import org.apache.tika.metadata.Metadata; import org.apache.tika.parser.AutoDetectParser; import org.apache.tika.parser.ParseContext; import org.apache.tika.sax.BodyContentHandler; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class DocumentIndexer { private static final Tika tika new Tika(); private static final AutoDetectParser parser new AutoDetectParser(); public static class DocumentInfo { String path; String content; String mimeType; String author; String title; long fileSize; Override public String toString() { return String.format(File: %s\nType: %s\nAuthor: %s\nTitle: %s\nSize: %d bytes\nContent: %.100s...\n, path, mimeType, author, title, fileSize, content); } } public static DocumentInfo indexDocument(File file) throws Exception { DocumentInfo info new DocumentInfo(); info.path file.getAbsolutePath(); info.fileSize file.length(); info.mimeType tika.detect(file); Metadata metadata new Metadata(); BodyContentHandler handler new BodyContentHandler(1000000); // 1MB限制 try (InputStream stream new FileInputStream(file)) { parser.parse(stream, handler, metadata, new ParseContext()); info.content handler.toString(); info.author metadata.get(Author); if (info.author null) info.author metadata.get(creator); info.title metadata.get(Title); if (info.title null) info.title file.getName(); } return info; } public static void main(String[] args) throws Exception { File directory new File(/path/to/documents); ListDocumentInfo documents new ArrayList(); Files.walk(directory.toPath()) .filter(Files::isRegularFile) .limit(100) .forEach(path - { try { documents.add(indexDocument(path.toFile())); } catch (Exception e) { System.err.println(Failed to index: path - e.getMessage()); } }); // 输出结果 documents.forEach(doc - System.out.println(doc)); // 全文搜索示例 String searchTerm important; System.out.println(\nSearching for: searchTerm); documents.stream() .filter(doc - doc.content.toLowerCase().contains(searchTerm.toLowerCase())) .forEach(doc - System.out.println(Found in: doc.path)); } }11. 版本升级说明从 1.x 到 2.x 的主要变化Java 11 要求API 包名从org.apache.tika.parser保持不变移除了部分过时 API性能优化和内存改进