はじめに
CSVフォーマットよく使うんですけど、実は罠が多いですよね。
なので自分でコーディングしないでライブラリを利用するのが大事なんですが、java用のopencsvを使うとヘッダに合わせてデータを読んでくれて便利なんです。
しかし、そのまま出力しようとすると、なんということでしょう。カラム名順にソートして出力してくれます。
世界中の人がそれで困っているようなのですが、簡潔に解決できましたので共有します。
コード
inline fun <reified T : Any> writeCsv(filename: String, data: List<T>): Unit {
FileWriter(filename).use { fileWriter ->
StatefulBeanToCsvBuilder<T>(fileWriter)
.withMappingStrategy(
HeaderColumnNameMappingStrategy<T>()
.apply {
type = T::class.java
val headers = FieldUtils.getAllFields(type)
.map {
it.getAnnotation(CsvBindByName::class.java).column
}
setColumnOrderOnWrite(compareBy { headers.indexOf(it) })
})
.build()
.write(data)
}
}
解説
HeaderColumnNameMappingStrategyが元のヘッダのカラム名でマッピングして読み込むためのものなのですが、実はそいつにsetColumnOrderOnWriteがいまして、それで出力順を変更できます。
しかし、文字列になってからなので文字列でしかこれだけだとソートできません。
なので、カラム名を定義順に取得しなおします。
その後、ソートを定義順にしてやれば出来上がりです。
参考リンク