我的日常

登录/注册
您现在的位置:论坛 盖世程序员(我猜到了开头 却没有猜到结局) 盖世程序员 > POI - 读取Excel2003、Excel2007或更高级的兼容性问题
总共48086条微博

动态微博

查看: 1552|回复: 0

POI - 读取Excel2003、Excel2007或更高级的兼容性问题

[复制链接]
admin    

1244

主题

544

听众

1万

金钱

管理员

  • TA的每日心情

    2021-2-2 11:21
  • 签到天数: 36 天

    [LV.5]常住居民I

    管理员

    跳转到指定楼层
    楼主
    发表于 2015-02-08 12:25:55 |只看该作者 |倒序浏览
    我们使用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

    科帮网 1、本主题所有言论和图片纯属会员个人意见,与本社区立场无关
    2、本站所有主题由该帖子作者发表,该帖子作者与科帮网享有帖子相关版权
    3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和科帮网的同意
    4、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任
    5、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
    6、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
    7、科帮网管理员和版主有权不事先通知发贴者而删除本文


    JAVA爱好者①群:JAVA爱好者① JAVA爱好者②群:JAVA爱好者② JAVA爱好者③ : JAVA爱好者③

    快速回复
    您需要登录后才可以回帖 登录 | 立即注册

       

    关闭

    站长推荐上一条 /1 下一条

    发布主题 快速回复 返回列表 联系我们 官方QQ群 科帮网手机客户端
    快速回复 返回顶部 返回列表