我们使用POI中的HSSFWorkbook来读取Excel数据。 + X3 k9 f: ~ ?% t; ?/ x3 L& ?public void test(File file) throws IOException { x9 i5 w1 u. B* d8 `" n InputStream inp = new FileInputStream(file);( y6 r( T: v, U1 q7 ?- d; D4 }( Z
HSSFWorkbook workbook = new HSSFWorkbook(inp);+ Z0 H% Q. S4 b* k1 y( M8 J+ g' k3 q
0 D; _$ o8 x9 a e) P
// workbook...遍历操作 . G2 U* X8 Y, f9 c+ m/ g } 1 w8 |* V4 J# E( |3 e+ X, {- I Q$ o$ S3 j7 C) T! E4 |! e. o
上边代码,读取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)”/ U. w) A5 O5 X4 k, T) b
查阅了资料,Excel2007版本的Excel文件需要使用XSSFWorkbook来读取,如下: ( y9 P0 T0 a- E, Gpublic void test(File file) throws IOException {/ h5 R' j+ L9 }/ z3 }& l8 ]
InputStream inp = new FileInputStream(file);: C0 O2 _3 Z% \# B$ X2 E2 y
XSSFWorkbook workbook = new XSSFWorkbook(inp);8 @- _6 O3 p9 r4 j9 {6 o' q( }2 A
, g3 J7 j8 a9 H% G( j2 } // workbook...遍历操作- X& z( R: G# {( f
} + G1 Q$ T. A0 z/ m. m: U! ~, \4 b4 p注意:XSSFWorkbook需要额外导入poi-ooxml-3.9-sources.jar和poi-ooxml-schemas-3.9.jar。( z6 q( c! C4 @- s3 a
这样,Excel2007的导入没问题了,但是导入Excel2003又报异常。 4 G2 d- F, v. \) f, j所以,在导入Excel的时候,尽量能判断导入Excel的版本,调用不同的方法。 ) U7 U8 n/ c1 o& Q8 i* A" T我想到过使用文件后缀名来判断类型,但是如果有人将xlsx的后缀改为xls时,如果使用xlsx的函数来读取,结果是报错;虽然后缀名对了,但是文件内容编码等都不对。& C9 G3 o: y# ^+ U2 D% u5 o
最后,推荐使用poi-ooxml中的WorkbookFactory.create(inputStream)来创建Workbook,因为HSSFWorkbook和XSSFWorkbook都实现了Workbook接口。代码如下:% _& I. T3 F: B& O
Workbook wb = WorkbookFactory.create(is); $ q0 l. W' }+ I" w+ \0 e Z4 z: N1 { * u. {& o! `0 f$ I, ^可想而知,在WorkbookFactory.create()函数中,肯定有做过对文件类型的判断,一起来看一下源码是如何判断的:& B+ E) _$ }4 {$ @$ n! }
/** 2 X8 ]& }; b+ b4 [ * Creates the appropriate HSSFWorkbook / XSSFWorkbook from 0 ^6 ]8 T) [, E3 i4 v * the given InputStream.; N9 h$ w7 g: @1 K1 p7 k }" v9 y
* Your input stream MUST either support mark/reset, or, O& \5 |4 b+ z, V/ u7 L
* be wrapped as a {@link PushbackInputStream}! 5 V D8 l2 s# B */ # H e4 J! L* `! [9 J public static Workbook create(InputStream inp) throws IOException, InvalidFormatException {: B. ~, d, X8 n# b3 m8 N3 n( ^
// If clearly doesn't do mark/reset, wrap up u( y; T+ i R! o* n
if(! inp.markSupported()) { 6 R" }5 g8 D8 N. ` inp = new PushbackInputStream(inp, 8); 9 P/ \- |$ \- @1 z/ E }9 k, K# X) k8 z, u# ~, t: X
0 u; u2 ~% z2 b& ^! @& h3 w
if(POIFSFileSystem.hasPOIFSHeader(inp)) { 5 K) r9 Y+ { @! S! ~4 o return new HSSFWorkbook(inp); ' C0 Y% }1 T9 M. x" e: D( V } , J$ j& x& V; S( F/ p2 A, N# R if(POIXMLDocument.hasOOXMLHeader(inp)) { . A$ P* P' A+ [. p2 d/ n) g; a return new XSSFWorkbook(OPCPackage.open(inp)); 2 a- {: L9 s. a- T }# Z4 k I8 P1 h4 H( A, L
throw new IllegalArgumentException("Your InputStream was neither an OLE2 stream, nor an OOXML stream");/ Q! s# Q6 { k& j4 j
}2 S; W0 ?2 d1 P+ Z: {8 L: W" @
& S7 E( x/ V& q& Q可以看到,有根据文件类型来分别创建合适的Workbook对象。是根据文件的头部信息去比对进行判断的,此时,就算改了后缀名,还是一样通不过。( E: ~% S; x8 @8 H' L( t
& C' z! Z+ R' u