2015-09-27 67 views
1

我试图解析一个逗号分隔字符串中使用:如何解析带引号的某些项目的逗号分隔线(CSV)?

val array = input.split(",") 

然后,我注意到,一些输入线有“”引号内:

data0, "data1", data2, data3, "data4-1, data4-2, data4-3", data5 

*请注意,数据不很干净,所以一些字段是引号内,而一些不


我如何分流,行成:

array(0) = data0 
array(1) = data1 
array(2) = data2 
array(3) = data3 
array(4) = data4-1, data4-2, data4-3 
array(5) = data5 
+3

解析CSV文件可能会非常棘手,因为它的行为围绕引号行,逗号和引号包含在引号值中。我建议拉入一个非常适合处理所有边缘案例的库。您可以考虑的选项包括[scala-csv](https://github.com/tototoshi/scala-csv)和[traversable-csv](http://labs.encoded.io/2012/04/09/reading -csv-文件正在斯卡拉最穿越的路/)。或者使用像[opencsv](http://opencsv.sourceforge.net/)这样的Java库。 – Shadowlands

+0

否则,如果你不想或不能使用一个库,你可以看看[这个SO答案](http://stackoverflow.com/questions/5063022/use-scala-parser-combinator-to-解析 - csv文件/ 5063652#5063652)或[this SO answer](http://stackoverflow.com/questions/32488364/whats-a-simple-scala-only-way-to-read-in-and-then -write-out-a-small-csv-file/32488453#32488453)查看其他人如何解决自己的CSV分析器问题。 – Shadowlands

+0

@Shadowlands您能否在回答中总结您的意见(因为我认为您已经展示了许多有价值的方法,其他人可以从中受益。)Thx。 –

回答

5

按我的意见:

解析CSV文件可以是出了名的棘手,因为它周围的引号和逗号和报价包含在报价值行为。我建议拉入一个非常适合处理所有边缘案例的库。

你可以考虑的选项包括scala-csvtraversable-csv。或者使用像opencsv这样的Java库。否则,如果您不想或不能使用库,您可以查看this SO answerthis SO answer以查看其他人是如何解决您自己的CSV解析器的。

+1

感谢Shadowlands!如果可能,我想使用图书馆。我在这里遇到的一个问题是没有“一个csv文件”,我会得到需要解析的“csv行”。有没有可以解析一行而不是整个文件的库?谢谢! – Edamame

-1

你实际上可以用正则表达式分割那一行。

val s = """data0, "data1", data2, data3, "data4-1, data4-2, data4-3", data5""" 

"""((".*?")|('.*?')|[^"',]+)+""".r.findAllIn(s).foreach(println) 

btw。任何可以解析csv文件的库也可以解析单个csv行。只需将该字符串包装到StringReader中即可。

+0

谢谢!请您详细说明一下“任何可解析csv文件的库都可以解析单个csv文件”。例如,如何修改以下文件解析器来解析单个csv行? CSVReader reader = new CSVReader(new FileReader(“yourfile.csv”)); – Edamame

+0

这应该像这样'CSVReader reader = new CSVReader(new StringReader(“data1,data2,data3”))' – SpiderPig

0

我会推荐使用CSV库来解析CSV数据 - 格式是一团糟,很难得到正确的结果。

我建议kantan.csv,主要是因为我是作者,但也因为它可以让你进一步比将CSV流转换为字符串数组列表更进一步。举个例子来说,下面的输入:

1,Foo,2.0 
2,Bar,false 

使用kantan.csv,你可以这样写:

import kantan.csv.ops._ 

new File("path/to/csv").asUnsafeCsvRows[(Int, String, Either[Float, Boolean])](',', false) 

对结果调用toList将产生:

List((1,Foo,Left(2.0)), (2,Bar,Right(false))) 

注意如何最后一列是浮点数或布尔值,但这是在迭代器的每个元素的类型中捕获的。

0

下面是我的解决方案来分析CSV行:

String[] res = row.split(";"); 
for (int i = 0; i < res.length; i++) { 
    res[i] = deQuotes(res[i]); 
} 
return res; 

删除引号与REGEXP:

static final Pattern PATTERN_DE_QUOTES = Pattern.compile("(?i)^\\\"(.*)\\\"$"); 

static String deQuotes(String s) { 
    Matcher matcher; 
    if ((matcher = PATTERN_DE_QUOTES.matcher(s)).find()) { 
     return matcher.group(1).replaceAll("\"\"", "\""); 
    } 
    return s; 
} 

我希望这会帮助你。

相关问题