使用Apache POI确定MS Excel文件类型

时间:2013-01-25 13:08:22

标签: java excel apache-poi

有没有办法在Apache POI中确定MS 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:
   ...
}

感谢。

5 个答案:

答案 0 :(得分:38)

宣传回答评论......

如果你要对文件做一些特别的事情,那么rjokelai's answer就是这样做的。

但是,如果您只是要使用HSSF / XSSF / Common SS用户模型,那么让POI为您执行此操作要简单得多,并使用WorkbookFactory来检测并打开类型您。你会做类似的事情:

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

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

然后,如果您需要做一些特别的事情,请测试它是HSSFWorkbook还是XSSFWorkbook。打开文件时,use a File rather than an InputStream if possible可以加快速度并节省内存。

如果您根本不知道文件是什么,请使用Apache Tika进行检测 - 它可以为您检测大量不同的文件格式。

答案 1 :(得分:22)

您可以使用:

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

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

这些基本上是WorkbookFactory#create(InputStream)用于确定类型

的方法

请注意,两种方法仅支持支持“mark”功能(或PushBackInputStream)的流,因此不支持简单的FileInputStream。使用BufferedInputStream作为包装器。因此,在检测之后,您可以简单地重复使用流,因为它将重置为起始点。

答案 2 :(得分:2)

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

示例代码段:

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

答案 3 :(得分:1)

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

的lib实现

我们可以模仿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
}

答案 4 :(得分:0)

这是我确定所请求文件属于Office类型的方式。

public static boolean isOfficeDoc(String filePath) {
         FileMagic fileMagic = getFileMagicObj(filePath);
            return fileMagic != null && (fileMagic == FileMagic.OLE2 || fileMagic == FileMagic.OOXML);
        }

    private static FileMagic getFileMagicObj(String filePath) {

        try (InputStream is = new FileInputStream(filePath);
             InputStream magicIS = FileMagic.prepareToCheckMagic(is)) {

            return FileMagic.valueOf(magicIS);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }