web-dev-qa-db-ja.com

Kotlinで行ごとにCSVを読み取る

単純なインポートアプリケーションを作成していて、CSVファイルを読み取り、結果をグリッドに表示し、CSVファイルの破損した行を別のグリッドに表示する必要があります。

それのための組み込みのlib、またはPythonicのような簡単な方法はありますか?

Androidでやっています。

16
Marcus Pólo

opencsv を使用します。

これは、CSVファイルを読み取る魅力のように機能します。

破損した行のログに関する限り、このロジックを使用してログを記録できます。

while(input.hasNextLine())
{
    try 
    {
         //execute commands by reading them using input.nextLine()
    }
    catch (ex: UserDefinedException)
    {
         //catch/log the exceptions you're throwing
         // log the corrupted line the continue to next iteration
    }
}

お役に立てれば。

5
Sudip

[2019年10月に編集]この回答を書いてから数か月後、 小山健太がKotlinターゲットライブラリを書いたhttps://github.com/doyaaaaaken/kotlin-csv にあり、opencsvよりもはるかによく見えます。

使用例:(詳細については、言及されているgithubページを参照してください)

_import com.github.doyaaaaaken.kotlincsv.dsl.csvReader

fun main() {
    csvReader().open("src/main/resources/test.csv") {
        readAllAsSequence().forEach { row ->
            //Do something
            println(row) //[a, b, c]
        }
    }
}
_

この例を使用した完全な最小限のプロジェクトについては、 https://github.com/PHPirates/kotlin-csv-reader-example を参照してください

opencsv:を使用した古い回答

提案されているように、 opencsv を使用すると便利です。これはやや最小限の例です:

_// You can of course remove the .withCSVParser part if you use the default separator instead of ;
val csvReader = CSVReaderBuilder(FileReader("filename.csv"))
        .withCSVParser(CSVParserBuilder().withSeparator(';').build())
        .build()

// Maybe do something with the header if there is one
val header = csvReader.readNext()

// Read the rest
var line: Array<String>? = csvReader.readNext()
while (line != null) {
    // Do something with the data
    println(line[0])

    line = csvReader.readNext()
}
_

docs に示されているように、すべての行を個別に処理する必要がない場合は、マップの形式で結果を取得できます。

_import com.opencsv.CSVReaderHeaderAware
import Java.io.FileReader

fun main() {
    val reader = CSVReaderHeaderAware(FileReader("test.csv"))
    val resultList = mutableListOf<Map<String, String>>()
    var line = reader.readMap()
    while (line != null) {
        resultList.add(line)
        line = reader.readMap()
    }
    println(resultList)
    // Line 2, by column name
    println(resultList[1]["my column name"])
}
_

Gradleの依存関係:_compile 'com.opencsv:opencsv:4.6'_またはGradle Kotlin DSLの場合:compile("com.opencsv:opencsv:4.6")(いつものように、 docs で最新バージョンを確認してください)。

5
PHPirate

使いやすさの点では、kotlinで記述されたcsvライブラリが優れています。

たとえば、私が作成した以下のライブラリを使用して、DSLのような方法でコードを記述できます。

https://github.com/doyaaaaaken/kotlin-csv

csvReader().open("test.csv") {
    readAllAsSequence().forEach { row ->
        //Do something with the data
        println(row)
    }
}
4
Koyama Kenta

CSVファイルの解析には、Kotlinコードでnet.sourceforge.javacsvを使用しました。 「Java」ライブラリですが、kotlin内では、次のように操作するのはかなり簡単です。

val reader = CsvReader("/path/to/file.csv").apply {
  trimWhitespace = true
  skipEmptyRecords = true
  readHeaders()
}

while (reader.readRecord()) {
  // do whatever
}
3
Ryba

率直に言って、KotlinでモダンなJava=機能を使用して単純なリーダーを作成することは非常に簡単です。これを確認してください(BOMを処理することを忘れないでください:-)):

fun processLineByLine(csv: File, processor: (Map<String, String>) -> Unit)  {
    val BOM = "\uFEFF"
    val header = csv.useLines { it.firstOrNull()?.replace(BOM, "")?.split(",") }
            ?: throw Exception("This file does not contain a valid header")

    csv.useLines { linesSequence ->
        linesSequence
                .drop(1)
                .map { it.split(",") }
                .map { header.Zip(it).toMap() }
                .forEach(processor)
    }
}

次のように使用できます(ファイル構造によって異なります)。

processLineByLine(File("./my-file.csv")) { row ->
    println("UserId: ${row["userId"]}")
    println("Email: ${row["email"]}")
}
3
mierzwid