Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Apache POI确定MS Excel文件类型_Java_Excel_Apache Poi - Fatal编程技术网

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

Java 使用Apache POI确定MS Excel文件类型,java,excel,apache-poi,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: ... b

有没有办法确定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:
   ...
}
谢谢。

您可以使用:

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

// For .xls
POIFSFileSystem.hasPOIFSHeader(new BufferedInputStream( new FileInputStream(file) ));
这些基本上是
WorkbookFactory创建(InputStream)
用于确定类型的方法


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

将注释升级为答案

如果你打算对这些文件做一些特殊的处理,那么这就是方法

但是,如果您只打算使用HSSF/XSSF/Common SS usermodel,那么让POI为您完成这项工作并使用它来检测并打开类型就简单多了。你可以这样做:

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

然后,如果您需要做一些特殊的事情,请测试它是
HSSFWorkbook
还是
XSSFWorkbook
。打开文件时,要加快速度并节省内存


如果你根本不知道你的文件是什么,用它来检测——它可以为你检测大量不同的文件格式。

基于org.apache.poi.ss.usermodel.WorkbookFactory的lib实现#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
}

这可以使用FileMagic类来完成。请参见下面的JavaDoc-

示例代码片段:


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

这是我确定请求的文件属于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;
        }
    }

你为什么要事先知道?您能否使用WorkbookFactory并让它为您创建合适的类型?这也是一个很好的变体,谢谢。谢谢。这是使用低级基于事件的只读访问来处理大型excel文件时检测文件类型的唯一方法。添加了只能使用“标记”支持流的信息。更新的代码示例.method
hasOOXMLHeader
在类
POIXMLDocument
中被删除,请在类不推荐的方法中使用它
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;
        }
    }