在Kotlin中逐行读取CSV

时间:2017-05-19 03:50:37

标签: android csv kotlin

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

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

我在Android上做这件事。

7 个答案:

答案 0 :(得分:4)

使用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
    }
}

希望这有帮助。

答案 1 :(得分:3)

我使用net.sourceforge.javacsv和我的Kotlin代码来解析CSV文件。它是一个“java”库,但在kotlin中,它就像

一样直接使用它
val reader = CsvReader("/path/to/file.csv").apply {
  trimWhitespace = true
  skipEmptyRecords = true
  readHeaders()
}

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

答案 2 :(得分:3)

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

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

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

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

答案 3 :(得分:2)

坦白地说,使用现代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)
    }
}

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

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

答案 4 :(得分:1)

根据建议,使用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所示,当您不需要分别处理每一行时,代码将变得更加整洁:

val values = CSVReaderHeaderAware(FileReader("filename.csv")).readMap()

答案 5 :(得分:1)

如果您更喜欢为每一行使用自己的数据类,您应该查看我的解决方案 https://github.com/gmuth/ipp-client-kotlin/blob/master/src/main/kotlin/de/gmuth/csv/CSVTable.kt

data class User(
        val name: String,
        val phone: String,
        val email: String
) {
    constructor(columns: List<String>) : this(
            name = columns[0],
            phone = columns[1],
            email = columns[2]
    )
}

CSVTable.print(FileInputStream("users.csv")) 
val userList = CSVTable(FileInputStream("users.csv"), ::User).rows

答案 6 :(得分:0)

我知道我来晚了,但是最近我在解析CSV时遇到了问题,似乎没有足够的库可以满足我的需求,所以我创建了自己的Kotlin CSV stream

此库很特殊,因为它不会在无效输入上引发异常,而是返回结果,这在某些情况下可能有用。