Pure Kotlin Multiplatform CSV reader and writer.
implementation("com.jsoizo:kotlin-csv:2.0.0")The multiplatform artifact resolves JVM, JS, and supported Kotlin/Native variants
from Kotlin Multiplatform projects. Published Native targets are
macosArm64, iosArm64, iosSimulatorArm64, linuxX64, linuxArm64, and mingwX64.
Single-platform Gradle projects can also depend on the platform artifact
directly, for example kotlin-csv-jvm, kotlin-csv-js,
kotlin-csv-macosarm64, or kotlin-csv-linuxx64.
implementation 'com.jsoizo:kotlin-csv:2.0.0'<dependency>
<groupId>com.jsoizo</groupId>
<artifactId>kotlin-csv-jvm</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.jsoizo</groupId>
<artifactId>kotlin-csv-js</artifactId>
<version>2.0.0</version>
</dependency>Snapshots of the next development version are published to Sonatype Central Portal Snapshots from the active development branch. SNAPSHOTs are unstable and may change at any time, but they let you try in-progress changes early.
Add the snapshots repository to your build, then declare the dependency with the corresponding -SNAPSHOT version
(see the active development branch's build.gradle.kts for the current value, for example 2.0.0-SNAPSHOT).
// settings.gradle.kts
dependencyResolutionManagement {
repositories {
mavenCentral()
maven("https://central.sonatype.com/repository/maven-snapshots/") {
mavenContent { snapshotsOnly() }
}
}
}// build.gradle.kts
implementation("com.jsoizo:kotlin-csv:<VERSION>-SNAPSHOT")The DSL builders return reusable, stateless instances; create them once and share them across calls.
import com.jsoizo.kotlincsv.csvReader
import com.jsoizo.kotlincsv.csvWriter
import com.jsoizo.kotlincsv.reader.readFromFile
import com.jsoizo.kotlincsv.reader.withHeader
import com.jsoizo.kotlincsv.writer.writeToFile
val reader = csvReader()
val writer = csvWriter()// From a String — eager
val rows: List<List<String>> = reader.readAll("a,b,c\nd,e,f")
// From a File — lambda owns the open resource and closes it on exit
reader.readFromFile(File("data.csv")) { rows ->
rows.forEach { println(it) }
}
// With a header row (returns LinkedHashMap to preserve column order)
reader.readFromFile(File("data.csv")) { rows ->
val records = rows.withHeader().toList()
println(records.first()["id"])
}reader.readFromFile(...) accepts String paths, kotlinx.io.files.Path,
and (on JVM) java.io.File. The block receives a cold
Sequence<List<String>>; take(n) and friends short-circuit cleanly
without parsing the rest of the file. For in-memory streams use
reader.read(source) (commonMain kotlinx.io.Source) or
reader.read(stream) (JVM java.io.InputStream).
val rows = listOf(
listOf("a", "b", "c"),
listOf("d", "e", "f"),
)
// To a String — eager
val csv: String = writer.writeAll(rows)
// To a File
writer.writeToFile(rows, File("out.csv"))writer.writeToFile(...) accepts String paths, kotlinx.io.files.Path,
and (on JVM) java.io.File. For in-memory streams use
writer.write(rows, sink) (commonMain kotlinx.io.Sink) or
writer.write(rows, stream) (JVM java.io.OutputStream). Both
Sequence<List<String>> and List<List<String>> are accepted as the row
source.
Reader and writer share a CsvDialect value object that holds the four
characters defining the CSV format itself: delimiter, quoteChar,
escapeChar, lineTerminator. Format-independent policies stay on the
respective Config.
val tsvReader = csvReader {
dialect = CsvDialect.TSV
skipEmptyLine = true
}
val customWriter = csvWriter {
dialect = CsvDialect(delimiter = ';', escapeChar = '\\')
quoteMode = WriteQuoteMode.ALL
}| Reader option | Default | Description |
|---|---|---|
dialect |
CsvDialect.RFC4180 |
Shared CSV format (delimiter / quote / escape / line terminator). |
skipEmptyLine |
false |
Drop rows that are entirely empty before the field-count check. |
excessFieldsRowBehaviour |
ERROR |
What to do when a row has more fields than the first row: ERROR / IGNORE / TRIM. |
insufficientFieldsRowBehaviour |
ERROR |
What to do when a row has fewer fields: ERROR / IGNORE / EMPTY_STRING. |
CsvFieldNumDifferentException.rowNum counts CSV rows after reader filters
such as skipEmptyLine; it is not a physical source line number.
| Writer option | Default | Description |
|---|---|---|
dialect |
CsvDialect.RFC4180 |
Shared CSV format (delimiter / quote / escape / line terminator). |
outputLastLineTerminator |
true |
Emit a trailing line terminator after the final row. |
quoteMode |
CANONICAL |
When to wrap fields in quoteChar: CANONICAL (only when needed), ALL, or NON_NUMERIC. |
Charset is JVM-only and is passed as an argument on the I/O call:
reader.readFromFile(File("data.csv"), charset = "Shift_JIS") { it.toList() }
writer.writeToFile(rows, File("out.csv"), charset = "UTF-16LE")commonMain and JS overloads are UTF-8 only.
BOM stripping on read defaults to ON (matches Excel-produced files):
reader.readFromFile(File("data.csv"), options = CsvReadIoOptions(stripBom = false))
writer.writeToFile(rows, File("out.csv"), options = CsvWriteIoOptions(prependBom = true))- Migration from kotlin-csv 1.x: see V2_MIGRATION_GUIDE.md.
- API documentation: generated by Dokka —
./gradlew dokkaHtmloutputs HTML tobuild/dokka/html/. - Change Logs: see GitHub releases.
Contributions, issues and feature requests are welcome!
If you have questions, ask away in Kotlin Slack's kotlin-csv room.
git clone git@github.com:jsoizo/kotlin-csv.git
cd kotlin-csv
./gradlew checkCopyright © 2024 jsoizo. This project is licensed under Apache 2.0.
This project was originally created by @doyaaaaaken. The initial work and contributions are greatly appreciated.