java中不可用string.split()解析csv,因其不处理引号包裹、逗号转义和换行嵌入;应使用apache commons csv并显式配置rfc4180格式、引号转义及bom处理。

Java里用String.split()直接切CSV字符串会出错
它只按分隔符机械切割,完全不处理CSV常见的引号包裹、逗号转义、换行嵌入等规则。比如"a,b","c""d",e会被切成5段而非3段,"foo,bar"里的逗号根本不是分隔符,但split(",")照切不误。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 别对含引号、内部逗号或换行的CSV字符串用
split()——哪怕看起来“简单” - 如果确定输入绝对干净(无引号、无换行、无内部逗号),且字段数固定,
split(",")可临时应急 - 注意
split()默认会丢弃末尾空字段,要保留得传-1:str.split(",", -1)
手动解析必须处理双引号转义和状态机逻辑
CSV规范里,双引号内的内容允许包含逗号、换行、甚至两个连续引号表示一个引号字符("a""b" → a"b)。这意味着你不能靠正则或单次扫描搞定,必须维护读取状态:是否在引号内、是否遇到转义引号。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 用
char数组遍历,设inQuotes = false和field = new StringBuilder() - 遇到
"时翻转inQuotes;若已在引号内且下一个是"(即""),跳过第二个引号并追加一个"到field - 只在
!inQuotes时响应逗号和换行,否则原样吞入field - 别忘了trim首尾空格——标准CSV不自动trim,但业务常需要
Apache Commons CSV比手写更稳,但要注意默认配置陷阱
直接引入commons-csv是合理选择,但它默认用CSVFormat.DEFAULT,而这个格式不支持双引号转义("" → "),也不处理CRLF换行,容易漏数据。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 显式用
CSVFormat.RFC4180或自定义:CSVFormat.DEFAULT.withFirstRecordAsHeader().withIgnoreEmptyLines(true) - 转义必须打开:
.withEscape('"')或更准的.withQuote('"').withQuoteMode(QuoteMode.ALL) - 解析单行字符串用
CSVParser.parse(str, format),别用parse(new StringReader(str))——后者多一层IO开销且对换行敏感 - 字段取值统一用
record.get("colName")或record.get(0),别直接操作String[]
边界场景:空字段、全空行、BOM头、混合编码
真实CSV常混入UTF-8 BOM(\uFEFF)、Windows换行(\r\n)、开头结尾空格、纯空行,甚至字段全是""。这些不会报错,但会导致字段错位或内容异常。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 读字符串前先检测并剥离BOM:
str.startsWith("\uFEFF") ? str.substring(1) : str - 用
String.trim()预处理整行再喂给CSV解析器,但注意别在引号内trim——所以最好由解析器自己做(如CSVFormat配.withIgnoreSurroundingSpaces(true)) - 空行默认被跳过,若需保留,关掉
withIgnoreEmptyLines(false),再检查record.isConsistent() - 别假设编码是UTF-8;若来源不可控,解析前明确指定Charset:
new InputStreamReader(new ByteArrayInputStream(bytes), StandardCharsets.UTF_8)
split()多三倍代码量——但少踩两次线上解析错位的坑,就值回票价。










