You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,它能自动处理复杂场景(如带引号的字段、换行字段等):

  1. 先引入Maven依赖:
<dependency>
    <groupId>com.opencsv</groupId>
    <artifactId>opencsv</artifactId>
    <version>5.6</version>
</dependency>
  1. 改进后的代码:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 08:30:55