确定与Apache POI MS Excel文件类型(Determine MS Excel file

2019-07-18 16:47发布

有没有一种方法来确定的Apache POI微软Office Excel文件类型? 我需要什么格式的Excel文件知道:在Excel '97(-2007)(的.xls)或Excel 2007 OOXML格式(.xlsx)。

我想我可以做这样的事情:

int type = PoiTypeHelper.getType(file);
switch (type) {
case PoiType.EXCEL_1997_2007:
   ...
   break;
case PoiType.EXCEL_2007:
   ...
   break;
default:
   ...
}

谢谢。

Answer 1:

推进到一个答案评论...

如果你打算做一些特殊处理这些文件,然后rjokelai的回答是做它的方式。

但是,如果你只是将要使用HSSF / XSSF /通用SS的usermodel,那么它要简单得多具有POI为你做,并使用WorkbookFactory有检测,为您揭开类型。 你会做这样的事情:

 Workbook wb = WorkbookFactory.create(new File("something.xls"));

要么

 Workbook wb = WorkbookFactory.create(request.getInputStream());

然后,如果你需要做一些特别的东西,测试,如果它是一个HSSFWorkbookXSSFWorkbook 。 打开文件时, 使用一个文件,而不是一个InputStream如果可能加快速度和节省内存。

如果你不知道你的文件是在所有的事,使用Apache的蒂卡做检测-它可以检测到不同的文件格式一个巨大的数字给你。



Answer 2:

您可以使用:

// For .xlsx
POIXMLDocument.hasOOXMLHeader(new BufferedInputStream( new FileInputStream(file) ));

// For .xls
POIFSFileSystem.hasPOIFSHeader(new BufferedInputStream( new FileInputStream(file) ));

这些基本上该方法WorkbookFactory#create(InputStream)用于确定所述类型使用

请注意,这两个方法,仅支持支持“标记”功能(或PushBackInputStream)流,不支持那么简单的FileInputStream。 使用的BufferedInputStream作为包装。 由于这个原因,检测后,你可以简单地重复使用流,因为它会先复位到起点。



Answer 3:

这可以通过使用FileMagic类来完成。 请参见下面的JavaDoc - https://poi.apache.org/apidocs/org/apache/poi/poifs/filesystem/FileMagic.html

示例代码段:

FileMagic.valueOf(inputStream).equals(FileMagic.OOXML) // XLSX



Answer 4:

基于的lib实施org.apache.poi.ss.usermodel.WorkbookFactory#create(java.io.InputStream)

我们可以模仿WorkbookFactory的逻辑,去除不相关的位,返回文件类型来代替。

public static TYPE fileType(File file) {
    try (
            InputStream inp = new FileInputStream(file)
    ) {
        if (!(inp).markSupported()) {
            return getNotMarkSupportFileType(file);
        }
        return getType(inp);
    } catch (IOException e) {
        LOGGER.error("Analyse FileType Problem.", e);
        return TYPE.INVALID;
    }
}

private static TYPE getNotMarkSupportFileType(File file) throws IOException {
    try (
            InputStream inp = new PushbackInputStream(new FileInputStream(file), 8)
    ) {
        return getType(inp);
    }
}

private static TYPE getType(InputStream inp) throws IOException {
    byte[] header8 = IOUtils.peekFirst8Bytes(inp);
    if (NPOIFSFileSystem.hasPOIFSHeader(header8)) {
        NPOIFSFileSystem fs = new NPOIFSFileSystem(inp);
        return fileType(fs);
    } else if (DocumentFactoryHelper.hasOOXMLHeader(inp)) {
        return TYPE.XSSF_WORKBOOK;
    }
    return TYPE.INVALID;
}

private static TYPE fileType(NPOIFSFileSystem fs) {
    DirectoryNode root = fs.getRoot();
    if (root.hasEntry("EncryptedPackage")) {
        return TYPE.XSSF_WORKBOOK;
    }
    return TYPE.HSSF_WORKBOOK;

}

public enum TYPE {
    HSSF_WORKBOOK, XSSF_WORKBOOK, INVALID
}


文章来源: Determine MS Excel file type with Apache POI