不会,StringTokenizer将连续逗号视为分隔符而非空字段,直接跳过导致丢失空字段,与CSV规范冲突;它也无法识别引号包裹的字段,对"a,b",c会错误拆分为"a"、"b"、"c"。

StringTokenizer 会把连续逗号当成一个分隔符吗?
不会。默认情况下 StringTokenizer 将连续分隔符(如 ,,)视为“空字段缺失”,直接跳过——这和标准 CSV 规范中“a,,b 应解析为 ["a", "", "b"]”完全冲突。遗留系统报文若含空字段,用它直接切分必然丢数据。
实操建议:
- 确认报文是否真有空字段:打印原始字符串,肉眼检查是否有
,,或开头/结尾的逗号 - 若存在空字段,
StringTokenizer必须配合returnDelims = true模式手动拼接,否则弃用 - 不要依赖
countTokens()获取字段数——它不统计空字段,结果不可靠
如何用 StringTokenizer 处理带引号的 CSV 字段?
不能。StringTokenizer 是纯字符切分器,对 "a,b",c 这类含内部逗号的字段完全无感知,会错误切出 "a、b"、c 三个碎片。遗留系统若用双引号包裹字段(哪怕只包部分),StringTokenizer 就不再适用。
实操建议:
- 检查报文样本:是否存在
"包裹、字段内含逗号或换行的情况 - 若存在,必须改用
OpenCSV或Apache Commons CSV,它们能正确处理引号转义 - 临时 workaround(仅限绝对干净的纯逗号分隔):先用正则预处理掉所有引号
str.replace(""", ""),但要确认业务允许丢弃引号语义
替代方案:用 String.split() 能解决空字段问题吗?
能,但要注意参数陷阱。直接写 str.split(",") 仍会丢尾部空字段;必须用 str.split(",", -1) 才保留全部字段(包括末尾的空字符串)。
实操建议:
- 用
split(",", -1)替代StringTokenizer是最轻量升级,兼容 JDK 1.4+ - 注意:正则模式下逗号是普通字符,无需转义;但若分隔符是点、星号等需
split("\.") - 性能上,短字符串(split() 创建数组略重,但换来语义正确更关键
- 避免
split(",")不带 limit 参数——这是遗留代码里最常踩的坑
真正安全的遗留 CSV 解析底线是什么?
如果报文来自不可控的旧系统,且文档缺失、样本混杂(有时带引号、有时空字段、偶尔还有换行),别硬刚 StringTokenizer 或手写 split()。这类场景下,连 String.split() 都可能因未处理引号嵌套而崩溃。
实操建议:
- 优先引入
opencsv-5.7.1.jar,用CsvParser+DefaultCsvReader,自动处理引号、空字段、换行 - 若无法加依赖,至少用
BufferedReader逐行读 + 正则预清洗(如合并跨行引号块),再交给split(",", -1) - 永远对解析后字段数做断言校验:
if (fields.length != EXPECTED_COL_COUNT) { log.warn("row mismatch: {}", line); }
复杂点在于:你永远不知道下一个报文里藏着什么。空字段、引号、BOM 头、混合编码……这些不是边缘情况,而是遗留系统的日常。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











