2015-09-27 47 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; 
} 

我希望這會幫助你。

相關問題