今天在处理Excel文件时候,发现对于以xls和xlsx为后缀的文件,用以下的代码处理时候抛 The supplied data appears to be in the OLE2 Format.异常,百思不得其姐!!! 明明都判断类型对应的文件类型也没毛病啊!!
try {
if ((filename.endsWith(".xls"))) {
workbook = new HSSFWorkbook(inputStream);
} else if (filename.endsWith(".xlsx")) {
workbook = new XSSFWorkbook(inputStream);
}
于是,我就想如何能得到workbook对象呢,是不是对象工厂构造然后返回对应的类型对象呢,百度之后发现有个WorkbookFactory对象构造workbook,查看源码,看到如下方法
public static Workbook create(InputStream inp) throws IOException, InvalidFormatException, EncryptedDocumentException {
return create((InputStream)inp, (String)null);
}
public static Workbook create(InputStream inp, String password) throws IOException, InvalidFormatException, EncryptedDocumentException {
InputStream is = FileMagic.prepareToCheckMagic(inp);
FileMagic fm = FileMagic.valueOf(is);
switch(fm) {
case OLE2:
NPOIFSFileSystem fs = new NPOIFSFileSystem(is);
return create(fs, password);
case OOXML:
return new XSSFWorkbook(OPCPackage.open(is));
default:
throw new InvalidFormatException("Your InputStream was neither an OLE2 stream, nor an OOXML stream");
}
}
上面的create方法对应下面方法,不得不说这重载的方法真的很巧妙。
private static Workbook create(NPOIFSFileSystem fs, String password) throws IOException, InvalidFormatException {
DirectoryNode root = fs.getRoot();
if (root.hasEntry("EncryptedPackage")) {
InputStream stream = DocumentFactoryHelper.getDecryptedStream(fs, password);
OPCPackage pkg = OPCPackage.open(stream);
return create(pkg);
} else {
boolean passwordSet = false;
if (password != null) {
Biff8EncryptionKey.setCurrentUserPassword(password);
passwordSet = true;
}
HSSFWorkbook var4;
try {
var4 = new HSSFWorkbook(root, true);
} finally {
if (passwordSet) {
Biff8EncryptionKey.setCurrentUserPassword((String)null);
}
}
return var4;
}
}
得出最终的解决方案:Workbook workbook=WorkbookFactory.create(inputStream)
唉,这不就是我想要的判断吗!!!成功解决OLE2和OOXML Format问题!!!