TA的每日心情 | 衰 2021-2-2 11:21 |
---|
签到天数: 36 天 [LV.5]常住居民I
|
我们使用POI中的HSSFWorkbook来读取Excel数据。
) S* k7 o" I4 F) M& }( ipublic void test(File file) throws IOException {( K1 k! c/ s4 @$ Q9 j$ V) O
InputStream inp = new FileInputStream(file);
0 L' d% u+ B2 Z2 } HSSFWorkbook workbook = new HSSFWorkbook(inp);. p# ~# d; S5 I* n; F
! X9 _* x3 I# Z: o8 ^
// workbook...遍历操作
0 \( d+ a v$ P9 ~2 L7 T; I+ _ }
# w2 n: `# P [
1 @+ c% X) G3 w$ I/ _上边代码,读取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)”
( ~3 ]5 G9 [, h$ G+ S查阅了资料,Excel2007版本的Excel文件需要使用XSSFWorkbook来读取,如下:
. P$ t7 ^, Y5 }8 T' G* P1 f1 Ipublic void test(File file) throws IOException { b+ Y/ }" y8 \& A( H5 a3 _- [
InputStream inp = new FileInputStream(file);# Z7 M+ Z6 C, W+ L, ^
XSSFWorkbook workbook = new XSSFWorkbook(inp);
* Q. F: s) e7 J5 c1 A ( G, `9 q( W v- t F& k
// workbook...遍历操作
5 u ~9 w: b7 ]6 u }8 h3 A! L& n& S( N
注意:XSSFWorkbook需要额外导入poi-ooxml-3.9-sources.jar和poi-ooxml-schemas-3.9.jar。
* g& K4 V: h; E0 ?: w& t# Y- x( M% }这样,Excel2007的导入没问题了,但是导入Excel2003又报异常。; `; r$ I$ A/ E7 t! E
所以,在导入Excel的时候,尽量能判断导入Excel的版本,调用不同的方法。
* k, v7 R2 U- Q# d4 _8 ]我想到过使用文件后缀名来判断类型,但是如果有人将xlsx的后缀改为xls时,如果使用xlsx的函数来读取,结果是报错;虽然后缀名对了,但是文件内容编码等都不对。$ S, ^: v# Y! l* t' w2 E: l
最后,推荐使用poi-ooxml中的WorkbookFactory.create(inputStream)来创建Workbook,因为HSSFWorkbook和XSSFWorkbook都实现了Workbook接口。代码如下:
) ]: ^& J6 y/ g! e8 |. TWorkbook wb = WorkbookFactory.create(is);% A4 @) s# ~. X3 o
: k2 I ?7 ^& I% w: F1 [2 J5 c2 P. }
可想而知,在WorkbookFactory.create()函数中,肯定有做过对文件类型的判断,一起来看一下源码是如何判断的:6 X+ h" @" B3 I. Z6 [$ {
/**
3 W( }+ m' e8 C) P/ [7 r * Creates the appropriate HSSFWorkbook / XSSFWorkbook from, ~( c. L3 K3 _1 M- U# \! D
* the given InputStream.
+ I+ J8 M1 M, @5 B * Your input stream MUST either support mark/reset, or
0 ]2 n- N& V( b) O * be wrapped as a {@link PushbackInputStream}!
" |) N/ T& Z# b */
4 n, m( R1 b& J( x public static Workbook create(InputStream inp) throws IOException, InvalidFormatException {' V* P9 q5 ^4 Q. a0 g \
// If clearly doesn't do mark/reset, wrap up X5 D; R: l9 ] t, g, Q+ V
if(! inp.markSupported()) {
9 Z- f0 e g1 x; T+ E) a; x7 c$ n inp = new PushbackInputStream(inp, 8);+ B7 i. K( B$ f( J2 @. P& |* t
}
! c7 w) w( C* Y5 Z8 l
4 M$ {5 ~' l. T' W' |! Q3 o if(POIFSFileSystem.hasPOIFSHeader(inp)) {4 e9 d, L( W% b( }
return new HSSFWorkbook(inp);1 R' u4 A" e9 K1 r
}
; [+ W5 n6 G$ u8 f2 | if(POIXMLDocument.hasOOXMLHeader(inp)) {
8 |+ v( R/ Z; f( d# t return new XSSFWorkbook(OPCPackage.open(inp));
- _. ]& W7 J w9 N2 F0 [ }8 x/ k0 T' i) ~7 m, R- Q7 z
throw new IllegalArgumentException("Your InputStream was neither an OLE2 stream, nor an OOXML stream");
& U; z. Y5 x; v) M5 W% ] }
0 K' ?2 K' L8 F. W3 K
' e7 z( ]- U2 r可以看到,有根据文件类型来分别创建合适的Workbook对象。是根据文件的头部信息去比对进行判断的,此时,就算改了后缀名,还是一样通不过。$ j$ I5 H ]" A5 r' n, o
' ?( X1 t' q& w7 F
|
|