opencsv读csv需显式指定编码(如gbk)和分隔符(如';'或' '),避免乱码和截断;写入前统一转字符串并设换行符;csvtobean要求列头与字段名字面完全匹配;大文件须用readnext()流式处理。

读取CSV时字段被截断或乱码,怎么设编码和分隔符
OpenCSV默认用UTF-8读文件,但Windows上Excel导出的CSV常是GBK或GB2312;如果没显式指定,CSVReader会按平台默认编码解析,中文直接变问号或乱码。分隔符也一样——逗号不是绝对的,有些CSV用分号或制表符,OpenCSV不自动识别,必须手动传参。
实操建议:
- 用
InputStreamReader包装FileInputStream,显式指定编码,再传给CSVReader - 构造
CSVReader时务必传CSVParser实例,用new CSVParserBuilder().withSeparator(';').build()定制分隔符 - 别依赖
new CSVReader(new FileReader(...)),FileReader无法指定编码,是坑的源头
示例片段:
Reader reader = new InputStreamReader(new FileInputStream("data.csv"), "GBK");
CSVReader csvReader = new CSVReader(reader, new CSVParserBuilder().withSeparator(' ').build());
写入CSV时引号、换行、逗号崩溃,怎么安全转义
OpenCSV默认对含逗号、换行、双引号的字段自动加引号并转义,但前提是字段得是字符串类型。如果传了null或数字没转成字符串,CSVWriter可能抛NullPointerException或输出格式错乱;更隐蔽的是,字段里有
,OpenCSV默认只处理
,Windows换行可能被当两行。
立即学习“Java免费学习笔记(深入)”;
实操建议:
- 写入前统一调用
String.valueOf(),避免null或原始类型直传 - 用
CSVWriter.DEFAULT_QUOTE_CHARACTER和CSVWriter.DEFAULT_ESCAPE_CHARACTER确认当前转义规则,不要假设 - 如需兼容Excel,写入时用
new CSVWriter(writer, ',', '"', '\', " ")显式设行结束符
错误现象举例:java.lang.NullPointerException出现在writeNext()调用处,大概率是数组里混了null。
用CsvToBean映射对象时字段对不上,为什么@CsvBindByName失效
CsvToBean靠字段名匹配列头,但默认严格区分大小写,且要求CSV首行必须是标准英文列名。如果CSV列头是“用户姓名”或“userName”,而Java字段叫userName,@CsvBindByName(column = "用户姓名")才生效;不加column参数就只认完全一致的小写英文名。
实操建议:
- 启用
StrictQuoteMode前先关掉——new CsvToBeanBuilder(reader).withIgnoreLeadingWhiteSpace(true).withType(MyClass.class).build() - 确保CSV第一行是纯ASCII列名,否则
@CsvBindByName基本失效 - 字段类型要和CSV内容能parse通,比如CSV里是"2024-01-01",Java字段却声明为
int,会静默跳过该字段
常见错误:CSV列头为“Order ID”,Java字段@CsvBindByName(column = "order id")——空格和大小写都必须完全一致。
大文件读取OOM或慢得离谱,怎么流式处理不加载全内存
OpenCSV本身是流式API,但很多人误用CSVReader.readAll(),它会把整个CSV读进ListreadNext()循环,每次只拿一行,但要注意:底层Reader不能提前关闭,否则后续readNext()返回null。
实操建议:
- 永远避免
readAll(),改用while ((line = reader.readNext()) != null)结构 - 配合try-with-resources时,只包裹
Reader,别把CSVReader也放进去——它的close()会关底层流 - 如果需随机访问或多次遍历,别硬扛,先存到数据库或临时文件,CSV不是数据库替代品
性能影响点:每行readNext()开销极小,但频繁GC字符串数组(尤其字段多)仍可观,字段数超20列时建议复用String[]数组实例。
最常被忽略的是CSV列头和Java字段名的映射契约——它不靠注解自动推断语义,只认字面精确匹配。一个空格、一个大小写、一个中文标点,都能让CsvToBean静默失败。










