Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package com.github.doyaaaaaken.kotlincsv.client
import com.github.doyaaaaaken.kotlincsv.dsl.context.CsvReaderContext
import com.github.doyaaaaaken.kotlincsv.dsl.context.ExcessFieldsRowBehaviour
import com.github.doyaaaaaken.kotlincsv.dsl.context.InsufficientFieldsRowBehaviour
import com.github.doyaaaaaken.kotlincsv.parser.CsvParser
import com.github.doyaaaaaken.kotlincsv.util.CSVAutoRenameFailedException
import com.github.doyaaaaaken.kotlincsv.util.CSVFieldNumDifferentException
import com.github.doyaaaaaken.kotlincsv.util.logger.Logger
import com.github.doyaaaaaken.kotlincsv.util.MalformedCSVException
/**
* CSV Reader class, which controls file I/O flow.
*
* @author doyaaaaaken
*/
class CsvFileReader internal constructor(
private val ctx: CsvReaderContext,
reader: Reader,
private val logger: Logger,
) {
private val reader = BufferedLineReader(reader)
private var rowNum = 0L
private val parser = CsvParser(ctx.quoteChar, ctx.delimiter, ctx.escapeChar)
/**
* read next csv row
* (which may contain multiple lines, because csv fields may contain line feed)
*
* @return return fields in row as List.
* or return null, if all line are already read.
*/
@Deprecated("We are considering making it a private method. If you have feedback, please comment on Issue #100.")
fun readNext(): List? {
return readUntilNextCsvRow("")
}
/**
* read all csv rows as Sequence
*/
fun readAllAsSequence(fieldsNum: Int? = null): Sequence> {
var expectedNumFieldsInRow: Int? = fieldsNum
return generateSequence {
@Suppress("DEPRECATION") readNext()
}.mapIndexedNotNull { idx, row ->
// If no expected number of fields was passed in, then set it based on the first row.
if (expectedNumFieldsInRow == null) expectedNumFieldsInRow = row.size
// Assign this number to a non-nullable type to avoid need for thread-safety null checks.
val numFieldsInRow: Int = expectedNumFieldsInRow ?: row.size
@Suppress("DEPRECATION")
if (row.size > numFieldsInRow) {
if (ctx.excessFieldsRowBehaviour == ExcessFieldsRowBehaviour.TRIM) {
logger.info("trimming excess rows. [csv row num = ${idx + 1}, fields num = ${row.size}, fields num of row = $numFieldsInRow]")
row.subList(0, numFieldsInRow)
} else if (ctx.skipMissMatchedRow || ctx.excessFieldsRowBehaviour == ExcessFieldsRowBehaviour.IGNORE) {
skipMismatchedRow(idx, row, numFieldsInRow)
} else {
throw CSVFieldNumDifferentException(numFieldsInRow, row.size, idx + 1)
}
} else if (numFieldsInRow != row.size) {
if (ctx.skipMissMatchedRow || ctx.insufficientFieldsRowBehaviour == InsufficientFieldsRowBehaviour.IGNORE) {
skipMismatchedRow(idx, row, numFieldsInRow)
} else if (ctx.insufficientFieldsRowBehaviour == InsufficientFieldsRowBehaviour.EMPTY_STRING) {
val numOfMissingFields = numFieldsInRow - row.size
row.plus(List(numOfMissingFields) { "" })
} else {
throw CSVFieldNumDifferentException(numFieldsInRow, row.size, idx + 1)
}
} else {
row
}
}
}
private fun skipMismatchedRow(
idx: Int,
row: List,
numFieldsInRow: Int
): Nothing? {
logger.info("skip miss matched row. [csv row num = ${idx + 1}, fields num = ${row.size}, fields num of first row = $numFieldsInRow]")
return null
}
/**
* read all csv rows as Sequence with header information
*/
fun readAllWithHeaderAsSequence(): Sequence