Apache TikaParser抛出不可捕获异常,如何实现捕获处理?
如何捕获Apache Tika处理Excel时的POI单元格格式异常
首先得明确:你外层的try-catch抓不到这个异常,是因为它根本没有向上传播到Tika的parse方法层面。这个异常是POI库在内部处理自定义单元格格式时抛出的,POI自己捕获了它并打印了WARNING日志,但没有把异常抛给上层的Tika调用逻辑,所以你的外层try-catch自然捕获不到。
下面给你两个可行的解决方向,按需选择:
方向一:抑制烦人的WARNING日志(最简单)
如果你的核心需求只是不想看到这个日志输出,直接通过日志框架配置把POI这个类的日志级别调低即可。比如用Logback的话,在logback.xml里加这段配置:
<logger name="org.apache.poi.ss.format.CellFormat" level="OFF"/>
如果用Log4j2,类似地在配置文件里把这个类的日志级别设为ERROR或OFF,这样就不会再打印这个警告了。
方向二:自定义Tika逻辑捕获内部异常(需要代码改造)
如果你需要在异常发生时执行自定义逻辑(比如标记这个文件、记录额外信息),那得自定义Tika处理Excel的逻辑,替换掉默认的Listener来捕获这个异常:
- 自定义一个
TikaHSSFListener子类,重写formatNumberDateCell方法,捕获里面的异常:
public class CustomTikaHSSFListener extends ExcelExtractor.TikaHSSFListener { public CustomTikaHSSFListener(ExcelExtractor extractor, BodyContentHandler handler, Metadata metadata) { super(extractor, handler, metadata); } @Override protected void formatNumberDateCell(CellValueRecordInterface cell, String formatString) { try { // 调用父类逻辑,这里会触发POI的格式处理 super.formatNumberDateCell(cell, formatString); } catch (IllegalArgumentException e) { // 在这里捕获你要抓的异常,执行自定义逻辑 System.err.println("处理单元格格式时出错: " + formatString); // 可以选择跳过这个单元格,或者用默认格式处理 super.handleCellContents(cell.getStringValue()); } } }
- 自定义
ExcelExtractor子类,重写创建Listener的方法:
public class CustomExcelExtractor extends ExcelExtractor { public CustomExcelExtractor(ParseContext context) { super(context); } @Override protected TikaHSSFListener createTikaHSSFListener(BodyContentHandler handler, Metadata metadata) { return new CustomTikaHSSFListener(this, handler, metadata); } }
- 把自定义的ExcelExtractor注册到Tika的AutoDetectParser里:
在你的TikaConfiguration初始化代码中,替换默认的OfficeParser逻辑:
// 初始化时,替换默认的OfficeParser List<Parser> parsers = new ArrayList<>(tikaConfig.getParser()); for (int i = 0; i < parsers.size(); i++) { if (parsers.get(i) instanceof OfficeParser) { // 创建自定义的OfficeParser,使用我们的ExcelExtractor OfficeParser customOfficeParser = new OfficeParser() { @Override protected ExcelExtractor createExcelExtractor(ParseContext context) { return new CustomExcelExtractor(context); } }; parsers.set(i, customOfficeParser); break; } } autoDetectParser = new AutoDetectParser(tikaConfig.getDetector(), new CompositeParser(parsers));
这样改造后,当POI抛出那个单元格格式异常时,你就能在自定义Listener的catch块里捕获并处理了。
内容的提问来源于stack exchange,提问作者Stefan Glasenhardt
相关产品推荐
相关产品推荐

