将不同的序列转换为CSV格式?

4
我们有许多返回Map [String,String](键,值)结果以存储在NoSQL数据库中的Scala类。其中一些结果实际上是Map [String,List]或Map [String,ArrayBuffer],因此我们在这些对象上使用.toString进行转换。这样就可以得到以下输出:
"ArrayBuffer(1,2,3,4)"

或者

"List(1,2,4)"

我们希望这些内容能够以纯CSV的形式呈现,需要用引号和转义字符。请问有没有适用于Scala的好用的CSV库?

3个回答

2

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

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

如果您希望序列化稍微复杂的数据结构: product-collections 将会将元组或者case类(任意Product)的集合序列化为csv,并且正确地转义引号。
scala> List ((1,"Jan"),
     | (2,"Feb"),
     | (3,"Mar","Extra column")).csvIterator.mkString("\n")
res41: String =
1,"Jan"
2,"Feb"
3,"Mar","Extra column"

product-collections 也可以直接写入 java.io.Writer。它具有针对同类元组的集合 CollSeq,不允许出现上述的“额外列”。

为了将您的原始数据转换为 product-collections 可处理的格式:

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"""

1

这里有一个类似的问题,应该涵盖了CSV部分。我已经查看了关于CSV的Scala问题,似乎没有任何建议可以创建CSV,而不仅仅是解析它。因此,我建议您研究一下Java库。


0

如果你想要CSV文件的标题,并且不介意使用自己的行映射函数来扩展trait,那么你可以像这样做。这个trait还包括了将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中,扩展特质可能会变得棘手,您可以选择不同的封装器来处理此部分。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接