Java读取含多字段CSV文件到ArrayList数组的实现问题
CSV读取到ArrayList的代码改进方案
原代码存在的问题
- 泛型缺失:
List list = new ArrayList<>();未指定泛型,遍历和操作时存在类型安全隐患,还需强制转换。 - 未处理表头:CSV第一行是字段名(name、company等),直接解析会把表头当成数据存入,导致数据错误。
- split方法局限性:用
split(",")拆分CSV不可靠——如果字段包含逗号(比如地址是"Main St, Apt 4B"),会直接分割字段,导致数组越界或数据错位。 - 编码兼容性差:
FileReader依赖系统默认编码,CSV文件编码(如UTF-8)与系统编码不一致时会出现乱码。 - 异常定位模糊:仅打印错误信息,无法快速定位是哪一行数据解析失败。
改进方案(无第三方库)
以下代码解决了上述问题,同时兼容带引号的逗号字段:
import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; public class CsvReader { public static void main(String[] args) { String path = "/home/arthur/Documentos/fe.csv"; List<Dates> list = new ArrayList<>(); int lineNumber = 0; try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(path), "UTF-8"))) { // 跳过表头行 String header = br.readLine(); lineNumber++; String line; while ((line = br.readLine()) != null) { lineNumber++; String[] fields = parseCsvLine(line); // 校验字段数量,避免数组越界 if (fields.length != 10) { System.err.println("第" + lineNumber + "行字段数量不符,跳过该行"); continue; } try { list.add(new Dates(fields[0], fields[1], fields[2], fields[3], fields[4], fields[5], fields[6], fields[7], fields[8], fields[9])); } catch (Exception e) { System.err.println("第" + lineNumber + "行解析失败:" + e.getMessage()); } } // 测试输出CEP字段 for (Dates dates : list) { System.out.println(dates.getCep()); } } catch (IOException e) { System.err.println("文件读取错误:" + e.getMessage()); } } // 自定义CSV行解析方法,处理带双引号的字段 private static String[] parseCsvLine(String line) { List<String> fields = new ArrayList<>(); StringBuilder currentField = new StringBuilder(); boolean inQuotes = false; for (char c : line.toCharArray()) { if (c == '"') { inQuotes = !inQuotes; } else if (c == ',' && !inQuotes) { fields.add(currentField.toString().trim()); currentField.setLength(0); } else { currentField.append(c); } } fields.add(currentField.toString().trim()); return fields.toArray(new String[0]); } }
更简洁的方案(使用OpenCSV库)
如果不想自己写解析逻辑,推荐用成熟的CSV解析库OpenCSV,它能自动处理复杂场景(如带引号的字段、换行字段等):
- 先引入Maven依赖:
<dependency> <groupId>com.opencsv</groupId> <artifactId>opencsv</artifactId> <version>5.6</version> </dependency>
- 改进后的代码:
import com.opencsv.CSVReader; import com.opencsv.exceptions.CsvValidationException; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; public class CsvReaderWithOpenCsv { public static void main(String[] args) { String path = "/home/arthur/Documentos/fe.csv"; List<Dates> list = new ArrayList<>(); try (CSVReader reader = new CSVReader(new InputStreamReader(new FileInputStream(path), "UTF-8"))) { // 跳过表头 reader.readNext(); String[] fields; int lineNumber = 2; // 数据从第二行开始 while ((fields = reader.readNext()) != null) { try { list.add(new Dates(fields[0], fields[1], fields[2], fields[3], fields[4], fields[5], fields[6], fields[7], fields[8], fields[9])); } catch (Exception e) { System.err.println("第" + lineNumber + "行解析失败:" + e.getMessage()); } lineNumber++; } // 测试输出CEP字段 for (Dates dates : list) { System.out.println(dates.getCep()); } } catch (IOException | CsvValidationException e) { System.err.println("CSV处理错误:" + e.getMessage()); } } }
额外注意事项
- 确保
Dates类的构造方法参数顺序,与CSV字段顺序(name、company、city、states、address、number、complement、neighborhood、cep、country)完全一致,避免数据错位。 - 如果CSV存在空字段,需在
Dates类的构造方法中处理空值,防止空指针异常。
内容的提问来源于stack exchange,提问作者Arthur Godoy
相关产品推荐
相关产品推荐

