在Kotlin中逐行读取CSV

rekjcdws  于 2022-12-30  发布在  Kotlin
关注(0)|答案(8)|浏览(272)

我正在编写一个简单的导入应用程序,需要读取CSV文件,在网格中显示结果,并在另一个网格中显示CSV文件的损坏行。
是否有任何内置的lib或任何简单的类似Python的方法?
我在安卓上做。

igetnqfo

igetnqfo1#

示例用法:(更多信息请参见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()
}

如文档中所示,当您不需要单独处理每一行时,您可以获得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"])
}

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

nzkunb0c

nzkunb0c2#

在易用性方面,Kotlin编写的csv库更好。
例如,你可以用我创建的下面的库以DSL的方式编写代码:
https://github.com/doyaaaaaken/kotlin-csv

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

omjgkv6w3#

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

希望这个有用。

vwkv1x7d

vwkv1x7d4#

我在Kotlin代码中使用了net.sourceforge.javacsv来解析CSV文件,它是一个“java”库,但是在Kotlin中使用它非常简单,比如

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

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

wswtfjt75#

坦率地说,使用现代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"]}")
}
e1xvtsh3

e1xvtsh36#

如果您更喜欢对每一行使用自己的数据类,那么应该看看我的解决方案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
qyzbxkaa

qyzbxkaa7#

我知道我有点晚了,但是我最近在解析CSV时遇到了问题,而且似乎没有足够好的库来满足我的需求,所以我创建了自己的库Kotlin CSV stream
这个库很特殊,因为它不会在无效输入时抛出异常,而是返回结果,这在某些情况下可能很有用。
下面的示例说明了它的易用性

val reader = CsvReader()
    .readerForType<CsvPerson>()
val people = reader.read(csv).map { it.getResultOrThrow() }.toList()
vxqlmq5t

vxqlmq5t8#

对于commons-csv版本1.9.0,已实现以下代码以获取结果。它使用CSVBuilder和CSVFormat获取带有跳过标题的记录,并根据第一行自动识别标题。

fun csvReader(file: MultipartFile): ResultListObject? {
    var result = ResultListObject()
    var csvFormat=CSVFormat.Builder.create().setHeader().setSkipHeaderRecord(true).build()
    var csvRecords = CSVParser(file.inputStream.bufferedReader(), csvFormat)
    
    csvRecords.forEach{csvRecords->
        rowRecord.field1=records.get("field1")
        rowRecord.field2=records.get("field2")
        ...
        ...
        result.add(rowRecord)
    }
    return result
}

相关问题