如何使用Scala解析带有换行符的文本文件以构建CSV文件?

时间:2018-01-26 06:03:40

标签: scala csv

我正在寻找解析此文本文件的帮助。我有这个文件的样本部分。它就像我希望变成CSV文件的文件中的名称列表。它看起来像这样:

Membership Date:  Jan 1, 1999        
Sponsors:  Mary Muray, Judy White,
                                    Ronald Zurch,
                                   Nina Lin,
                                   Nathan Garton,
                                   Howard Ross  
    Comments:  This are great members to have on our team.

以下是带引号(“)的预期输出:

“Membership Date:  Jan 1, 1999",
"Sponsors:  Mary Muray, Judy White, Ronald Zurch, Nina Foss, Nathan Garton, Howard Ross“,
“Comments:  This are great members to have on our team.” 

请注意,输出有3个字段。赞助商字段已取出换行符,因此所有名称都在一个字段中。

我的代码如下所示:

val filename: String = "/data/members.csv"
val lines = Source.fromFile(filename).getLines().toList
val ToLines = lines.dropWhile(line => !line.startsWith("Sponsor: ")).takeWhile(line  => !line.startsWith("Comments: ")).toSeq

最后一行代码将每个名称放在序列中的每个元素中,任何行都放在列表中自己的单独元素中。我需要帮助才能将所有名称都放在一个元素中,因此当我将结果保存为CSV时,赞助商字段的所有名称都在一个字段中。如果这没有意义,请告诉我。

3 个答案:

答案 0 :(得分:1)

您的代码在列表中的自己的元素中没有一个名称,它将每行作为一个元素。您还需要使用split(",")将名称分隔为自己的元素。之后,您可以使用mkString(", ")将列表合并为一个字符串。下面是一些代码执行此操作以及一些修剪空格和删除空列表元素。请注意,在Sponsors: dropWhile Sponsor:期间,您在文件中val sponsors = lines .dropWhile(line => !line.startsWith("Sponsors: ")) .takeWhile(line => !line.startsWith("Comments: ")) .flatMap(_.split(",")) .map(_.trim()) .filter(_.nonEmpty) .mkString(", ") ,这些文件需要保持一致才能正常工作。

Sponsors:  Mary Muray, Judy White, Ronald Zurch, Nina Lin, Nathan Garton, Howard Ross

这将给出一个单独的字符串:

val data = lines.head.trim()
val comments = lines.last.trim()

val members = List(data, sponsors, comments).map(s => "\"" + s + "\"").mkString(",\n")

将日期和评论添加到赞助商:

"Membership Date:  Jan 1, 1999",
"Sponsors:  Mary Muray, Judy White, Ronald Zurch, Nina Lin, Nathan Garton, Howard Ross",
"Comments:  This are great members to have on our team."

会给你一个字符串如下:

filter

根据您的想法,您可以修改上述代码以获得最终结果。

答案 1 :(得分:1)

我知道这不是一种优雅的方式,但我尝试使用典型的循环而不是使用任何内置函数来解决这个问题。这个逻辑可以根据你的实际需求进行调整

 val file: BufferedSource = Source.fromFile("file name")
 val lines = file.getLines()
 val result = scala.collection.mutable.ArrayBuffer.empty[String]

 val temp = new StringBuilder();

    for (line <- lines) {
      if (temp.mkString.contains(":") && line.contains(":")) {    
        result.append("\"" + temp.toString + "\"")
        temp.clear()
      }
      temp.append(line.trim())
    }

    if (temp.length > 0) result.append("\"" + temp.toString() + "\"")
    temp.clear()

    result.foreach { println(_) }

输出

"Membership Date:  Jan 1, 1999"
"Sponsors:  Mary Muray, Judy White,Ronald Zurch,Nina Lin,Nathan Garton,Howard Ross"
"Comments:  This are great members to have on our team."

答案 2 :(得分:1)

在我看来,你可能会更灵活地确定什么是新线,什么是线延续。

io.Source.fromFile("members.csv")
  .getLines
  .foldLeft(List.empty[String]){(all,line) =>
    if (line.contains(": ")) line.trim :: all
    else all.head + " " + line.trim :: all.tail
  }.reverse.mkString("\"", "\",\n\"", "\"")

mkString()的单次调用会添加所有请求的引号和逗号分隔符。