在Kotlin中逐行读取CSV

Mar*_*ólo 13 csv android kotlin

我正在编写一个简单的导入应用程序,需要读取CSV文件,在网格中显示结果并在另一个网格中显示CSV文件的损坏行.

是否有任何内置的lib或任何简单的类似pythonic的方式?

我是在android上做的.

Koy*_*nta 7

在易用性方面,kotlin 编写的 csv 库更好。

例如,您可以使用我创建的以下库以 DSL 的方式编写代码:

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

csvReader().open("test.csv") {
    readAllAsSequence().forEach { row ->
        //Do something with the data
        println(row)
    }
}
Run Code Online (Sandbox Code Playgroud)


Sud*_*dip 5

使用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
    }
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助。


PHP*_*ate 5

[2019年10月编辑]在我写了这个答案的几个月后,Koyama Kenta写了一个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]
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

有关此示例的完整的最小项目,请参阅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()
}
Run Code Online (Sandbox Code Playgroud)

如在文档中所见,当您不需要分别处理每一行时,可以以Map的形式获得结果:

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"])
}
Run Code Online (Sandbox Code Playgroud)

Gradle compile 'com.opencsv:opencsv:4.6'或Gradle Kotlin DSL的依赖关系compile("com.opencsv:opencsv:4.6")(一如既往,请检查docs中的最新版本)。


mie*_*wid 5

坦率地说,使用现代 Java 功能在 Kotlin 中制作一个简单的阅读器是很容易的,检查这个(记住处理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)
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以按如下方式使用它(取决于您的文件结构):

processLineByLine(File("./my-file.csv")) { row ->
    println("UserId: ${row["userId"]}")
    println("Email: ${row["email"]}")
}
Run Code Online (Sandbox Code Playgroud)

  • 看起来不符合 rfc 标准,字段中允许换行(https://tools.ietf.org/html/rfc4180) (2认同)