All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ceesvee.CsvWriter.scala Maven / Gradle / Ivy

The newest version!
package ceesvee

import scala.annotation.switch

object CsvWriter {

  /**
   * Encode rows into CSV lines prepending the given header.
   */
  def encodeWithHeader[T](
    header: Iterable[String],
    rows: Iterator[T],
  )(implicit E: CsvRecordEncoder[T]): Iterator[String] = {
    Iterator(fieldsToLine(header)) ++ encode(rows)
  }

  /**
   * Encode rows into CSV lines.
   */
  def encode[T](
    rows: Iterator[T],
  )(implicit E: CsvRecordEncoder[T]): Iterator[String] = {
    rows.map(E.encode(_)).map(fieldsToLine(_))
  }

  def fieldsToLine(fields: Iterable[String]): String = {
    fields.map(quoteField(_)).mkString(",")
  }

  def quoteField(field: String): String = {
    val _field = field.replaceAll("\"", "\"\"")
    if (needsQuoting(field)) s"\"${_field}\"" else _field
  }

  def needsQuoting(s: String): Boolean = {
    s.headOption.exists(isWhitespace(_)) ||
    s.lastOption.exists(isWhitespace(_)) ||
    containsSpecialCharacter(s)
  }

  def isWhitespace(c: Char): Boolean = {
    c == ' ' || c == '\t'
  }

  @SuppressWarnings(Array("org.wartremover.warts.Var", "org.wartremover.warts.While"))
  private def containsSpecialCharacter(s: String): Boolean = {
    var i = 0
    var contains = false

    while (i < s.length) {
      (s(i): @switch) match {

        case '"' | ',' | '\n' | '\r' =>
          contains = true
          i = s.length

        case _ =>
          i += 1
      }
    }

    contains
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy