将各种Seq转换为CSV?

时间:2010-10-04 16:56:26

标签: scala csv

我们有许多Scala类返回Map [String,String](键,值)结果,以便存储在NoSQL数据库中。一些结果实际上是Map [String,List]或Map [String,ArrayBuffer],所以我们在那些对象上使用.toString进行转换。这为我们提供了如下输出:

"ArrayBuffer(1,2,3,4)"

"List(1,2,4)"

我们不希望包含对象类型,而是根据需要将这些内容写成直接的CSV,引号和转义字符。有一个很好的CSV库可以很好地与Scala一起使用吗?

3 个答案:

答案 0 :(得分:1)

Here's一个类似的问题,应该涵盖CSV部分。我查看了有关csv的Scala问题,似乎没有任何关于创建 csv的东西的建议,而不仅仅是解析它。所以我会研究Java库。

答案 1 :(得分:0)

如果您只想序列化单个列表或数组而不正确转义引号等:

scala> List(1,2,3,4).mkString(",")
res39: String = 1,2,3,4

如果您希望序列化稍微复杂的数据结构: product-collections将序列化元组或案例类(任何产品)的集合到csv并正确地转义引号。

scala> List ((1,"Jan"),
     | (2,"Feb"),
     | (3,"Mar","Extra column")).csvIterator.mkString("\n")
res41: String =
1,"Jan"
2,"Feb"
3,"Mar","Extra column"

产品系列也会直接写入java.io.Writer。它有一个专门用于同源元组的集合CollSeq,它不允许"额外的列"上方。

并将原始数据转换为可由产品集合处理的格式:

scala> CollSeq(scala.collection.mutable.ArrayBuffer("a","b","quoted \"stuff\""):_*)
res52: com.github.marklister.collections.immutable.CollSeq1[String] =
CollSeq((a),
        (b),
        (quoted "stuff"))

scala> res52.csvIterator.mkString("\n")
res53: String =
"a"
"b"
"quoted ""stuff"""

答案 2 :(得分:0)

如果您还想要CSV文件的标题,并且不介意必须使用自己的行映射功能扩展特征,则可以执行此类操作。这个特性还包括加载CSV的相反部分,还需要您自己提供的映射功能。

trait CsvSerialization[T] {

  import java.io.File
  import helpers.FileIO._

  def fileName: String
  def basePath: String
  def csvColumnHeaders: Array[String]
  def itemToRowMapper(item: T): List[String]
  def rowToItemMapper(row: Map[String, String]): T

  val filePath = basePath + File.separator + fileName

  def cached = new File(filePath).exists

  def toCsv(collection: Iterable[T]) = {
    println(basePath)
    makePathRecursive(basePath) // you can skip this in your code
    val writer = com.github.tototoshi.csv.CSVWriter.open(new File(filePath), append = false)      
    writer.writeRow(csvColumnHeaders.toList)   
    writer.writeAll(collection map  { collectionItem =>
      val csvRowSerialized = itemToRowMapper(collectionItem)
      require (
        csvRowSerialized.length == csvColumnHeaders.length,
        s"csv row mapping function returned ${csvRowSerialized.size} items whereas column headers has ${csvColumnHeaders.size} items")
      csvRowSerialized
    } toSeq)
    writer.close
  }

  def fromCsv: List[T] = {
    val reader = com.github.tototoshi.csv.CSVReader.open(new File(filePath))
    val collection = reader.allWithHeaders map { csvRow => 
      require (
        csvRow.size == csvColumnHeaders.length,
        s"csv row mapping function returned ${csvRow.size} items whereas column headers length has ${csvColumnHeaders.size} items")
      rowToItemMapper(csvRow)
    }
    reader.close
    collection
  }

}

对于此代码,需要在项目中包含此基础CSV库:https://github.com/tototoshi/scala-csv

请注意,扩展特征在Scala中可能会变得棘手,您可以为此部分选择不同的包装。