【问题标题】:NullpointerException when trying to read XLSX file尝试读取 XLSX 文件时出现 NullpointerException
【发布时间】:2013-08-16 13:53:39
【问题描述】:

我目前有这段代码可以使用 apache POI 打开一个 xlsx 文件

File existingXlsx = new File("/app/app.xlsx");
System.out.println("File Exists: " + existingXlsx.exists());

Workbook workbook = WorkbookFactory.create(existingXlsx);

当我尝试执行此操作时,我得到以下输出

File Exists: true
java.lang.NullPointerException
    at org.apache.poi.xssf.usermodel.XSSFWorkbook.onDocumentRead(XSSFWorkbook.java:270)
    at org.apache.poi.POIXMLDocument.load(POIXMLDocument.java:159)
    at org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(XSSFWorkbook.java:186)
    at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:91)

我尝试打开的文件可以在 Excel 中打开并正确显示数据,我该怎么做才能让 POI 读取 XLSX 文件?

这是损坏的文件;

https://mega.co.nz/#!FJMWjQKI!CzihQgMVpxOQDTXzSnb3UFYSKbx4yFTb03-LI3iLmkE

编辑

我也试过了,还是一样的错误;

Workbook workbook = new XSSFWorkbook(new FileInputStream(existingXlsx));

编辑

我找到了引发异常的行;

WorkbookDocument doc = WorkbookDocument.Factory.parse(getPackagePart().getInputStream());
this.workbook = doc.getWorkbook();

Map<String, XSSFSheet> shIdMap = new HashMap<String, XSSFSheet>();
for(POIXMLDocumentPart p : getRelations())
{
    if(p instanceof SharedStringsTable) sharedStringSource = (SharedStringsTable)p;
    else if(p instanceof StylesTable) stylesSource = (StylesTable)p;
    else if(p instanceof ThemesTable) theme = (ThemesTable)p;
    else if(p instanceof CalculationChain) calcChain = (CalculationChain)p;
    else if(p instanceof MapInfo) mapInfo = (MapInfo)p;
    else if (p instanceof XSSFSheet) {
        shIdMap.put(p.getPackageRelationship().getId(), (XSSFSheet)p);
    }
}

stylesSource.setTheme(theme); <== BREAKS HERE

编辑

经过一些研究 POI 似乎无法找到 styles.xml 和 workbook.xml,我觉得这很奇怪,因为像 TextWrangler 这样显示存档结构的简单阅读器向我显示了样式 xml。

我该如何解决这个问题?是否有可以插入存档的默认 styles.xml 和 workbook.xml?

【问题讨论】:

  • 你有资源吗?你可以调试它
  • 您对文件有读取权限吗?您还确定它不是目录吗?除此之外,我会按照@nachokk 所说的进行调试。
  • 查看编辑,该行与stylesSource.setTheme(theme);
  • 您使用的是什么版本的 Apache POI?如果它不是最新的,您是否尝试过升级?
  • 我能够下载您的 xls 表并通过 POI 3.9 阅读它。 style.xml 和 workbook.xml 由 POI 自动检索/生成。在我的运行中,没有 NullPointerException,因为 stylesSource 在 for 循环中已正确初始化。我怀疑你的类路径或使用的 jars 有问题。你能创建一个新的非常简单的 xls 文件,在 1 个单元格中只添加 1 个值,看看你是否能够使用当前设置读取它?只是想确认您是否遇到问题将所有 xls 文件或只是这个..

标签: java excel apache-poi


【解决方案1】:

现在我已经下载了最新的包:

  • poi-src-3.9-20121203.zip(作为源)
  • xmlbeans-2.6.0.zip
    • jsr173_1.0_api.jar
    • resolver.jar
    • xbean.jar
    • xbean_xpath.jar
    • xmlbeans-qname.jar
    • xmlpublic.jar
  • ooxml-schemas-1.1.jar
  • dom4j-1.6.1.jar
  • commons-codec-1.8.jar
  • commons-logging-1.1.3.jar
  • ant.jar (ant 1.7)

并且您的 test2.xlsx 被毫无问题地读取:

  public static void main(String arg []){
    try {
      //File existingXlsx = new File("/app/app.xlsx");
      File existingXlsx = new File("c:/Java/poi-3.9/test-data/__theproblem/test2.xlsx");
      System.out.println("File Exists: " + existingXlsx.exists());

      Workbook workbook = WorkbookFactory.create(existingXlsx);

    } catch (Exception e) {
      e.printStackTrace();
    }
  }

您确定按照 POI 文档的建议使用 ooxml-schemas-1.1.jar

编辑

嗯。它也适用于我的 jar。

  1. 我已从 poi-bin-3.9-20121203.tar.gz 下载 http://poi.apache.org/download.html

  2. 在 Eclipse 中新建一个项目,从 zip 中提取所有的 jar:

    • lib/commons-codec-1.5.jar
    • lib/commons-logging-1.1.jar
    • lib/dom4j-1.6.1.jar
    • lib/junit-3.8.1.jar
    • lib/log4j-1.2.13.jar
    • lib/poi-3.9-20121203.jar
    • lib/poi-examples-3.9-20121203.jar
    • lib/poi-excelant-3.9-20121203.jar
    • lib/poi-ooxml-3.9-20121203.jar
    • lib/poi-ooxml-schemas-3.9-20121203.jar
    • lib/poi-scratchpad-3.9-20121203.jar
    • lib/stax-api-1.0.1.jar
    • lib/xmlbeans-2.3.0.jar
  3. 添加测试 xlsx:
    • 测试数据/test2.xlsx
  4. 测试 Java:
    • src/XlsxReadTest1.java

来源:

    import java.io.File;
    import org.apache.poi.ss.usermodel.Workbook;
    import org.apache.poi.ss.usermodel.WorkbookFactory;

    public class XlsxReadTest1 {
      public static void main(String arg []){
        try {

          File existingXlsx = new File("c:/Java/__Work/apache_POI/poi-3.9-bin/test-data/test2.xlsx");
          System.out.println("File Exists: " + existingXlsx.exists());

          Workbook workbook = WorkbookFactory.create(existingXlsx);

          System.out.println("A1: " + workbook.getSheetAt(0).getRow(0).getCell(0).getStringCellValue());

        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }
  1. 运行。 (用jdk1.7.0_07、jdk1.6.0_31试过)

  2. 结果:

    File Exists: true
    A1: Testing Edit
    

Testing Edit”是文件第一张纸上第一个单元格的内容。

我认为,您可以从头开始尝试。

(也许你在项目中使用了其他jar,谁在类加载器中干扰了这个jar?类加载器是个狡猾的家伙……)

【讨论】:

  • 我正在使用二进制 zip 中包含的 poi-ooxml-schemas-3.9-20121203.jar,不知道是哪个版本的模式。
  • 我尝试使用 ooxml-schemas-1.1.jar 但仍然导致 NullPointerException
  • dom4j, xmlbeans 是最新版本吗?非常有趣,它在第一次运行时把我吵醒了。 (经过几个小时的搜寻所需的 jar - 如上所述 - 编译 POI 源...;))(它在我的家用电脑上,我将在 CET 晚上尝试使用 POI jar。)
  • (我已经编辑了答案,用罐子添加了第二阶段。)
  • 我试过你的确切代码和二进制文件。我仍然收到 NullpointerException,您在哪个平台上运行?问题可能出在我使用 OSX 的某个地方吗?
【解决方案2】:

我猜你只是使用了错误的 poi 包。 尝试下载以下内容或从页面中查看最新版本。

我在 Eclipse 开发中测试了以下内容:

http://www.apache.org/dyn/closer.cgi/poi/release/bin/poi-bin-3.9-20121203.zip 提取它,并将所有 jar 包含到您的 eclipse 库中

我结合了 user1234 的答案和我自己的方法,两者都在你的 test2.xlsx 上工作

            import java.io.File;
            import java.io.FileInputStream;
            import java.io.FileNotFoundException;
            import java.io.IOException;

            import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
            import org.apache.poi.openxml4j.opc.OPCPackage;
            import org.apache.poi.ss.usermodel.Cell;
            import org.apache.poi.ss.usermodel.Row;
            import org.apache.poi.ss.usermodel.Sheet;
            import org.apache.poi.ss.usermodel.Workbook;
            import org.apache.poi.xssf.extractor.XSSFExcelExtractor;
            import org.apache.poi.xssf.usermodel.XSSFWorkbook;
            import org.apache.xmlbeans.XmlException;


            public class Main {

                /**
                 * @param args
                 */
                public static void main(String[] args) {
                    //      File existingXlsx = new File("app.xlsx");

                    File file = new File("test2.xlsx");
                    FileInputStream fs;
                    try {
                        fs = new FileInputStream(file);

                        OPCPackage xlsx = OPCPackage.open(fs);
                        XSSFExcelExtractor xe = new XSSFExcelExtractor(xlsx);
                        System.out.println(xe.getText());


                    } catch (FileNotFoundException e1) {
                        e1.printStackTrace();
                    } catch (XmlException e) {
                        e.printStackTrace();
                    } catch (OpenXML4JException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                    /// -------------- Another approach

                    File existingXlsx = new File("test2.xlsx");
                    System.out.println("File Exists: " + existingXlsx.exists());

                    try {
                        Workbook workbook = new XSSFWorkbook(new FileInputStream(
                            existingXlsx));

                        Sheet worksheet = workbook.getSheet("Filter criteria");
                        Row row1 = worksheet.getRow(0);
                        Cell cellA1 = row1.getCell((short) 0);
                        String a1Val = cellA1.getStringCellValue();


                        System.out.println("A1: " + a1Val);

                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                }

            }

终于得到了结果:

【讨论】:

  • 我试过你的确切代码和二进制文件。我仍然收到 NullpointerException,您在哪个平台上运行?问题可能出在我使用 OSX 的某个地方吗?
  • 我用eclipse 3.7.2在windows7-64bit上运行
【解决方案3】:

如果您想阅读 .xlsx,请尝试此代码(使用 apache poi 3.9):

    File file = new File("/app/app.xlsx");
    FileInputStream fs = new FileInputStream(file);
    OPCPackage xlsx = OPCPackage.open(fs);
    XSSFExcelExtractor xe = new XSSFExcelExtractor(xlsx);
    System.out.println(xe.getText());

上面的代码应该显示文件app.xlsx的内容。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2016-05-04
  • 2013-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多