LoginSignup
3
2

More than 3 years have passed since last update.

【Java】Apache TikaでExcel(に限らず色々な)ファイルをパースする【Kotlin】

Last updated at Posted at 2019-06-08

やりたいこと

xlsxファイルをパースします。
今回はApache Tikaを用いてパースを行います。

パースする内容

今回は以下のような内容のファイルをパースしていきます。

補足として、今回の記事を書くにあたって確認用に利用したファイルはGoogle Docsのスプレッドシートで生成したものなので、純正/サードパーティ性のソフトから生成した場合もちゃんと動くのか確認できていません。
また、実際のファイルではフォントをバラバラに変更したりしていましたがパース結果に影響は有りませんでした。

シート1
hoge ふが ピヨ
fizz バッズ fizzBuzz

やりかた

ライブラリを導入してparseすればできます。
今回はxml系(含xlsx)ファイルのみに対応してパースする方法と、Tikaにファイル種別を検出してもらって自動でパースする方法との2通りを試します。

Apache Tika Parsersを導入する

Mavenから導入します。
検証には1.21を使いました。

xml系データのみをパースする方法

OOXMLParserを用いてパースすることでできます。
パースした結果はContentHandler(今回はBodyContentHandler)に格納されます。
BodyContentHandlerからの情報取得はtoString以外の方法を見つけられませんでした。

サンプルコードは以下の通りです。
src/main/resourcesに入っているxml系ファイルをパースします。
注意点として、xml系でない(=OOXMLParserがパースできない)ファイルを入れると落ちます。

実行結果はTikaにファイル種別を検出してもらって自動でパースする方法と同じなので割愛します。

import org.apache.tika.parser.ParseContext
import org.apache.tika.parser.microsoft.ooxml.OOXMLParser
import org.apache.tika.sax.BodyContentHandler
import org.apache.tika.metadata.Metadata as TikaMetadata
import java.io.File
import java.io.FileInputStream

fun main() {
    val parser = OOXMLParser() // XML系データ用のパーサー
    val metaData = TikaMetadata()
    val context = ParseContext()
    val handler = BodyContentHandler() // パース結果が格納されるハンドラ

    File(System.getProperty("user.dir") + "/src/main/resources").listFiles().forEach {
        parser.parse(FileInputStream(it), handler, metaData, context)
        println(handler.toString())
    }
}

Tikaにファイル種別を検出してもらって自動でパースする方法

先ほどのサンプルコードからパーサーをAutoDetectParserに差し替えることで実現できます。

import org.apache.tika.parser.AutoDetectParser
import org.apache.tika.parser.ParseContext
import org.apache.tika.sax.BodyContentHandler
import org.apache.tika.metadata.Metadata as TikaMetadata
import java.io.File
import java.io.FileInputStream

fun main() {
    val parser = AutoDetectParser() // ファイル種別まで自動検出するパーサー
    val metaData = TikaMetadata()
    val context = ParseContext()
    val handler = BodyContentHandler() // パース結果が格納されるハンドラ

    File(System.getProperty("user.dir") + "/src/main/resources").listFiles().forEach {
        println("-------------")
        println(it.name)

        parser.parse(FileInputStream(it), handler, metaData, context)
        println(handler.toString())
        println("-------------")
    }
}

実行結果

スプレッドシートで落とせるzip以外のファイル形式を全て回してみました。

-------------
xls_for_test.xlsx
シート1
    hoge    ふが  ピヨ
    fizz    バッズ   fizzBuzz



-------------
-------------
xls_for_test - シート1.csv
シート1
    hoge    ふが  ピヨ
    fizz    バッズ   fizzBuzz


hoge,ふが,ピヨ
fizz,バッズ,fizzBuzz

-------------
-------------
xls_for_test.ods
シート1
    hoge    ふが  ピヨ
    fizz    バッズ   fizzBuzz


hoge,ふが,ピヨ
fizz,バッズ,fizzBuzz
    hoge
    ふが
    ピヨ

    fizz
    バッズ
    fizzBuzz




???
Page 
??? (???)
00/00/0000, 00:00:00
Page  / 

-------------
-------------
xls_for_test - シート1.pdf
シート1
    hoge    ふが  ピヨ
    fizz    バッズ   fizzBuzz


hoge,ふが,ピヨ
fizz,バッズ,fizzBuzz
    hoge
    ふが
    ピヨ

    fizz
    バッズ
    fizzBuzz




???
Page 
??? (???)
00/00/0000, 00:00:00
Page  / 

hoge ふが ピヨ

fizz バッズ fizzBuzz



-------------
-------------
xls_for_test - シート1.tsv
シート1
    hoge    ふが  ピヨ
    fizz    バッズ   fizzBuzz


hoge,ふが,ピヨ
fizz,バッズ,fizzBuzz
    hoge
    ふが
    ピヨ

    fizz
    バッズ
    fizzBuzz




???
Page 
??? (???)
00/00/0000, 00:00:00
Page  / 

hoge ふが ピヨ

fizz バッズ fizzBuzz


hoge    ふが  ピヨ
fizz    バッズ   fizzBuzz

-------------

感想

とりあえずxlsxに限らず様々な形式のファイルがパースできてよかったです。
ただ、パースした結果の出力はBodyContentHandlerの形式だと辛いので、より目的に合致するものが無いか探していきます。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2