Search code examples
javakotlinsupercsv

How to add whitespace in place of null values when reading from a file using SuperCSV?


I am trying to add column to the end of a file without changing the contents using SuperCSV and kotlin.

I cannot use CSVWriter due to limitation of resources.

So, my idea is to read from the original file row by row and add that to a string and have the result be used as a byte array.


    fun addColumnToCSV(csvData: ByteArray, columnName: String, columnValue: String): ByteArray {
        val prefs = CsvPreference.Builder(CsvPreference.STANDARD_PREFERENCE)
            .useQuoteMode(NormalQuoteMode()).build()

        val mapReader = CsvMapReader(BufferedReader(InputStreamReader(csvData.inputStream())), prefs)
        val readHeader = mapReader.getHeader(true)

        var row = mapReader.read(*readHeader)
        var csv: String = readHeader.joinToString(",", postfix = ",$columnName\n")
        while (row != null) {
            val rowValue=readHeader.map { header-> row.getOrDefault(header,"\\s") }
            csv += rowValue.joinToString(",", postfix = ",$columnValue\n")
            row = mapReader.read(*readHeader)
        }
        csv = csv.trim()
        mapReader.close()
        return csv.toByteArray()
    }

So, I have an example here and written a test for it.

    @Test
    fun `should add extra column in csv data when there are missing values`() {
        val columnName = "ExtraColumn"
        val columnValue = "Value"
        val expectedCSV = "Name,LastName,$columnName\n" +
                "John,Doe,$columnValue\n" +
                "Jane,,$columnValue"

        val csvData = "Name,LastName\n" + "John,Doe\n" + "Jane,"

        val csv = addColumnToCSV(csvData.toByteArray(), columnName, columnValue)

        Assertions.assertThat(String(csv)).isEqualTo(expectedCSV)
    }

This test fails because the actual of csv data is

Name,LastName,ExtraColumn
John,Doe,Value
Jane,null,Value

I want it to be this, so that I am not changing the existing values that are present in the csv file.

Name,LastName,ExtraColumn
John,Doe,Value
Jane,,Value

I have tried with row.getOrDefault(header,"") its still the same result. How do I achieve this?


Solution

  • The problem seems to be on this line:

    val rowValue=readHeader.map { header-> row.getOrDefault(header,"\\s") }
    

    Without testing this, I would say that there's a null in row at index LastName, hence default value in getOrDefault is not applied because map contains the key.

    Please try something like this:

    val rowValue=readHeader.map { header-> row.getOrDefault(header,"\\s") ?: "" }