有没有办法在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:
...
}
感谢。
答案 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)
我们可以模仿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;
}
}