java讀取csv,處理特殊字符(引號 逗號 斜杠 等)。注意,wps和office對于/"、, 的處理不同。
感謝群友大小姐、黑貓的指導(dǎo)
附大小姐的git:https://github.com/yingyulou/Published-Articles
此算法原理是"手工編碼的確定性有窮自動機(jī)"算法,有興趣的可以學(xué)習(xí)下
import java.util.ArrayList;
import java.util.List;
/**
* @Description csv格式轉(zhuǎn)換工具類
* 1 4個引號。你看到第一個,就從沒引號進(jìn)有引號狀態(tài),然后看到第二個,這時候,你不知道這個引號是第一個引號的配對,還是和第三個引號連起來的。你就需要一個新的狀態(tài)
* 在這個狀態(tài)下,如果你第三個看到的是引號,則說明是引號2連,輸出一個引號,然后狀態(tài)改成在引號內(nèi)。否則,說明之前那個引號是結(jié)束引號,狀態(tài)就改成在引號外,同時繼續(xù)處理我自己
* 2 ps:wps和office對于/"、, 的處理不同。
* @Author wujiahao
* @Date 2021/11/3
**/
public class CsvFileParseUtil {
/**
* 狀態(tài)值
*/
private enum LexerStage {
/**
* 開始
*/
Start,
/**
* 普通
*/
Common,
/**
* 引號
*/
Quote,
/**
* 連續(xù)2個引號
*/
DoubleQuote,
}
private static class Parser {
StringBuilder splitStr = new StringBuilder();
LexerStage lexerStage;
//返回的分割后的數(shù)組
List<String> splitList = new ArrayList();
//分隔符
String delim = ",";
public Parser(String delim) {
this.lexerStage = LexerStage.Start;
this.delim = delim;
}
}
private static void parseCsvLineCommonHelper(Parser parser, char curChar) {
if (parser.delim.equals(curChar + "")) {
parser.lexerStage = LexerStage.Start;
parser.splitList.add(parser.splitStr.toString());
parser.splitStr.setLength(0);
} else {
parser.splitStr.append(curChar);
}
}
private static void parseCsvLineStartHelper(Parser parser, char curChar) {
switch (curChar) {
case '"':
parser.lexerStage = LexerStage.Quote;
break;
default:
parser.lexerStage = LexerStage.Common;
parseCsvLineCommonHelper(parser, curChar);
break;
}
}
private static void parseCsvLineQuoteHelper(Parser parser, char curChar) {
switch (curChar) {
case '"':
parser.lexerStage = LexerStage.DoubleQuote;
break;
default:
parser.splitStr.append(curChar);
break;
}
}
private static void parseCsvLineDoubleQuoteHelper(Parser parser, char curChar) {
switch (curChar) {
case '"':
parser.lexerStage = LexerStage.Quote;
parser.splitStr.append('"');
break;
default:
parser.lexerStage = LexerStage.Common;
parseCsvLineCommonHelper(parser, curChar);
}
}
public static List<String> parseCsvLine(String csvLineStr, String delim) throws Exception {
Parser parser = new Parser(delim);
for (char curChar : csvLineStr.toCharArray()) {
switch (parser.lexerStage) {
case Start:
parseCsvLineStartHelper(parser, curChar);
break;
case Common:
parseCsvLineCommonHelper(parser, curChar);
break;
case Quote:
parseCsvLineQuoteHelper(parser, curChar);
break;
case DoubleQuote:
parseCsvLineDoubleQuoteHelper(parser, curChar);
break;
default:
throw new Exception("Invalid LexerStage value");
}
}
parser.splitList.add(parser.splitStr.toString());
return parser.splitList;
}
public static void main(String[] args) throws Exception {
parseCsvLine(("\"4|\",|"),",").
stream().
forEach(a -> System.out.println(a));
}
}