我们使用POI中的HSSFWorkbook来读取Excel数据。- ?) r2 H) l1 y) {
public void test(File file) throws IOException { ; Q: a* [6 n* z, a/ ` InputStream inp = new FileInputStream(file); e" O) V5 M7 X7 ? HSSFWorkbook workbook = new HSSFWorkbook(inp);7 W% N ]/ ]3 X# f% I
- s. d- H0 v, Y
// workbook...遍历操作 ) C" a- ^: j2 c* U" q- @& x# ? }; C E- C% A. m I* B/ g1 f
0 [3 S9 G: e+ Q6 x
上边代码,读取Excel2003(xls)的文件没问题,但是一旦读取的是Excel2007(xlsx)的文件,就会报异常:“The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF)” L- ~; r+ y# l. u* U+ h+ R查阅了资料,Excel2007版本的Excel文件需要使用XSSFWorkbook来读取,如下: & A0 H% ]8 `) [7 [3 @public void test(File file) throws IOException {, B$ t0 f, ]/ T, o
InputStream inp = new FileInputStream(file);4 v" q# Z' M4 V- T, r6 F
XSSFWorkbook workbook = new XSSFWorkbook(inp);/ y+ Z" h2 p: }
& [. i$ j- A9 A8 H* [ // workbook...遍历操作 3 X4 ?5 W; u% L; E0 c } 2 G% Y f4 G7 M4 h& `- f. D/ z, ]注意:XSSFWorkbook需要额外导入poi-ooxml-3.9-sources.jar和poi-ooxml-schemas-3.9.jar。 % ?7 N! i% @# T( Z& ?" b这样,Excel2007的导入没问题了,但是导入Excel2003又报异常。9 U% f8 R# @0 l' J
所以,在导入Excel的时候,尽量能判断导入Excel的版本,调用不同的方法。# \. D1 a3 K3 z# D. F+ }7 f
我想到过使用文件后缀名来判断类型,但是如果有人将xlsx的后缀改为xls时,如果使用xlsx的函数来读取,结果是报错;虽然后缀名对了,但是文件内容编码等都不对。$ c9 o( V% q% }# _
最后,推荐使用poi-ooxml中的WorkbookFactory.create(inputStream)来创建Workbook,因为HSSFWorkbook和XSSFWorkbook都实现了Workbook接口。代码如下: 8 Z2 b3 l A2 w, d( u) h* yWorkbook wb = WorkbookFactory.create(is);: n% }+ M' a* z, g$ `3 ?
) n- G) ]' X3 P7 B2 e
可想而知,在WorkbookFactory.create()函数中,肯定有做过对文件类型的判断,一起来看一下源码是如何判断的:2 T( J( D# W- d) x f; n
/** & U7 [7 Z7 J' W6 ]6 r * Creates the appropriate HSSFWorkbook / XSSFWorkbook from- X0 m7 L. A# a
* the given InputStream.% E G( \0 y7 F/ q |- i; q/ S
* Your input stream MUST either support mark/reset, or# \( X! f5 f: d; H
* be wrapped as a {@link PushbackInputStream}!. l( v: Q5 Q( m$ }, u `
*/3 ^% k% k( V: }0 N! b1 C, [
public static Workbook create(InputStream inp) throws IOException, InvalidFormatException {$ |0 c' E& K# f( X" M+ c) Y; a: i5 p
// If clearly doesn't do mark/reset, wrap up5 Z9 G4 X, {8 u6 W9 l& R+ `% l6 |
if(! inp.markSupported()) {8 _6 i! q( Q& T7 L" k* T
inp = new PushbackInputStream(inp, 8);& a u' g$ Y, [ g" @, K
} ! ~& c; v# I4 x: P/ s ' s4 y3 x. E) X" d3 o% ~2 g
if(POIFSFileSystem.hasPOIFSHeader(inp)) {0 ?6 h, U) x2 N% d6 z. h9 s
return new HSSFWorkbook(inp); & Q8 ~# c+ m- _% [4 Z }4 j! p% w v" u) U) I1 o G
if(POIXMLDocument.hasOOXMLHeader(inp)) {% ~& G# }( X2 m j# g
return new XSSFWorkbook(OPCPackage.open(inp));6 y* O+ P9 G: ~
}. M% q7 O- a1 v6 R/ v5 y# {& z
throw new IllegalArgumentException("Your InputStream was neither an OLE2 stream, nor an OOXML stream"); ; h4 a# H1 K- I& e } , q' _; t; t6 d2 Z 4 T6 v. a7 r. Y/ \4 g2 ^1 x( @( {可以看到,有根据文件类型来分别创建合适的Workbook对象。是根据文件的头部信息去比对进行判断的,此时,就算改了后缀名,还是一样通不过。 , M0 a, c. x C+ U" g* g- x& _0 K a) L, X