最近接到一個需求,需要在數據庫中配置按照csv格式配置數據,並將獲取的數據通過正則表達式進行切分處理。
這個需求主要是因爲最近項目要加一個數據表達式解析框架jeval,要處理的數據可能包含各種特殊字符,沒有一個簡單通用的模板可以使用。(具體這個框架的使用我另起一篇來實現)
有些人可能說自己可以自定義一個函數實現字符串數據的切分,理論上這樣是可以的 ,主要你的分隔符足夠複雜,另外這樣還有風險是不能確保你要切割的字符串不會包含這種特殊字符。
正則劃分csv我網上找了一個正則表達式,親測有效。博客鏈接如下:正則切分csv文件
核心代碼如下
public static List<String> splitCSV(String txt) {
String reg = "\\G(?:^|,)(?:\"([^\"]*+(?:\"\"[^\"]*+)*+)\"|([^\",]*+))";
// 即 \G(?:^|,)(?:"([^"]*+(?:""[^"]*+)*+)"|([^",]*+))
Matcher matcherMain = Pattern.compile(reg).matcher(txt);
Matcher matcherQuoto = Pattern.compile("\"\"").matcher("");
// matcherMain.reset(txt)
// System.out.println(matcherMain.groupCount());
List strList = new ArrayList();
while (matcherMain.find()) {
String field;
if (matcherMain.start(2) >= 0) {
field = matcherMain.group(2);
} else {
field = matcherQuoto.reset(matcherMain.group(1)).replaceAll("\"");
}
strList.add(field);
}
return strList;
}
剛開始同事拿到這個正則發現老是切割的不對,即不能通過這個正則切割出自己預料的結果。
有兩種可能:
1、配置的測試數據不是csv格式數據,導致正則切割的有問題
2、本來這個正則表達式就有問題,導致我們配置的數據無法正確切割
爲了驗證第一種情況,首先需要了解csv格式的數據都有神馬特點,特別是對於一些複雜的,比如包含換行符,逗號,雙引號,單引號之類的我們數據該如何配置才能保證正確切割。
網上上了幾篇博客,大致彙總如下:
具體文件格式:
- 每條記錄佔一行 以逗號爲分隔符
- 逗號前後的空格會被忽略
- 字段中包含有逗號,該字段必須用雙引號括起來
- 字段中包含有換行符,該字段必須用雙引號括起來
- 字段前後包含有空格,該字段必須用雙引號括起來
- 字段中的雙引號用兩個雙引號表示
- 字段中如果有雙引號,該字段必須用雙引號括起來
- 第一條記錄,可以是字段名
我認真研讀逐條研讀了上面的內容,然後配置後發現自己配置的複雜表達式切割出來還是有問題。最後實在看不出自己哪一步錯了,就自己創建了一個csv文件。把自己期望要切割的demo配置逐條配置在csv文件中。保存後用notepad++打開這個文件可以看到經過格式化的配置內容。
最後發現是我要切割的字符串裏面的雙引號需要變成兩個雙引號。
知道問題後就好處理了,我會在每次切割之前先把數據裏面的一個雙引號用字符串替換函數替換成兩個雙引號,最後組裝配置後進行切割,發現結果滿足預期。
關於csv格式描述,參考了下面的博客
csv格式描述博客