1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Kotlinx Serialization Csvについての備忘録

Last updated at Posted at 2025-01-29

背景

CMPでデスクトップアプリを作るとなったときに、CSVを読み込む必要が出てきたのでどうやるんだろう…と思って調べたところ、Serializationを使ってCSVをパースできるKotlinx-Serialization-Csvなるものがあったので、備忘録として使い方を残しておきます

Kotlinx Serialization Csvについて

詳細はわからないのですが、SerializationのCsv版のようです
CsvとSerializableの双方向変換ができるようなので、デスクトップアプリとかでは便利なライブラリなのですが、まだドキュメントもなくほとんど情報がないようです(なにか知っている方いましたらコメントでも共有していただけるとありがたいです)
また、jvmでしか書かれていないのでiOS等では動作はしませんので、Windowsデスクトップアプリで使うのが一番よくあるユースケースかなと思われます

使い方

ドキュメントは無いようなので自分の解釈含んだ解説になります
こちらのファイルを見ると生成したCsvクラスを元にdecode(Csv→Serializable),encode(Serializable→Csv)出来るようです

@OptIn(ExperimentalSerializationApi::class)
fun main() {
    // Csvクラスを生成
    val csv = Csv { hasHeaderRecord = true }

    val records = listOf(
        Person("Neo", "Thomas A. Anderson", Appearance(Gender.MALE, 37, 1.86)),
        Person("Trinity", null, Appearance(Gender.FEMALE, null, 1.74))
    )
    // エンコード
    val serialized = csv.encodeToString(ListSerializer(Person.serializer()), records)
    println(serialized)
}

また、機能は以下になるようです

関数名 機能
encodeToString SerializableからCSVの文字列を出力
encodeTo SerializableからAppendable形式で出力(ファイル出力等に用いる)
decodeToString CSV文字列(String)からSerializableを生成
decodeTo CSVファイルのReaderからSerializableを生成

単純にcsvファイルを読み込むならばReaderを用意して渡してあげることでSerializable化することができます

以下は例(CSVがShift-JISかつMemberというSerializableクラスがある場合)

val path = member.csv
FileInputStream(path).use { fis ->
    InputStreamReader(fis, "Shift_JIS").use { isr ->
        val members = csv.decodeFrom(
            ListSerializer(Member.serializer()),
            isr,
        )
        println("$members")
    }
}

また、Csvクラスにはいろんなオプションがあるので用途に応じて使う形になりそうです(以下適当に翻訳)

オプション デフォルト値 説明
delimiter , 列間の区切り文字。
recordSeparator \n レコード区切り文字。
quoteChar " 列の値を引用するために使用される引用文字。
quoteMode MINIMAL 列の値を引用するかどうかを決定するために使用される引用モード。
• ALL:すべてのフィールドを引用します。
• ALL_NON_NULL:すべての非nullフィールドと特殊文字を含むフィールドを引用します。
• ALL_NON_NUMERIC:すべての非数値フィールドと特殊文字を含むフィールドを引用します。
• MINIMAL:特殊文字を含むフィールドを引用します。
• NONE:フィールドを引用しません(CsvConfiguration.escapeCharの設定が必要です)。
escapeChar null 列の値内の予約文字をエスケープするために使用される文字。
nullString 空文字列 null値を識別するための値。
ignoreEmptyLines true 解析中に空行を無視します。
hasHeaderRecord false 最初の行をヘッダーレコードとして扱います。
headerSeparator . 階層的なヘッダー名を区切るために使用される文字。
ignoreUnknownColumns false 不明な列を無視します(hasHeaderRecordが有効な場合のみ効果があります)。
hasTrailingDelimiter false 末尾のレコードが区切り文字で終わる場合。

テンプレートとしてDefaultとRfc4180が用意されているようなのでこちらで間に合うなら使うと良いかも

sealed class Csv(val config: CsvConfig) : StringFormat {
    ...
    /**
    * Standard Comma Separated Value format.
    * Settings are:
    * CsvConfig. delimiter = ','
    * CsvConfig. quoteChar = '"'
    * CsvConfig. recordSeparator = "\n"
    * CsvConfig. ignoreEmptyLines = true
    */
    companion object Default : Csv(CsvConfig.Default) {

        /**
         * [RFC 4180](http://tools.ietf.org/html/rfc4180) *Comma Separated Value* format.
         *
         * Settings are:
         * - [CsvConfig.delimiter] = `','`
         * - [CsvConfig.quoteChar] = `'"'`
         * - [CsvConfig.recordSeparator] = `"\r\n"`
         * - [CsvConfig.ignoreEmptyLines] = `false`
         */
        val Rfc4180: Csv
            get() = Impl(CsvConfig.Rfc4180)
    }

総括

ドキュメントが無いとはいえ、Serializerが使えて簡単に変換出来るのは便利なのでWindowsアプリでCSV使いたい!って方は知っておくと良いかも

参考文献

1
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
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?