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

如何读取含继承类的CSV文件并映射至指定Java类?

问题解答

1. 读取CSV文件的实现方式

可以用Java原生API或第三方库实现,以下是两种常用方案:

原生Java实现

通过BufferedReader逐行读取并分割列:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class CsvReader {
    public static List<String[]> readCsv(String filePath) throws IOException {
        List<String[]> rows = new ArrayList<>();
        try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
            String line;
            br.readLine(); // 跳过表头
            while ((line = br.readLine()) != null) {
                String[] columns = line.split(",");
                rows.add(columns);
            }
        }
        return rows;
    }
}

第三方库(OpenCSV)实现

依赖Maven坐标:

<dependency>
    <groupId>com.opencsv</groupId>
    <artifactId>opencsv</artifactId>
    <version>5.6</version>
</dependency>

读取代码:

import com.opencsv.CSVReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.List;

public class OpenCsvReader {
    public static List<String[]> readCsv(String filePath) throws IOException {
        try (CSVReader reader = new CSVReader(new FileReader(filePath))) {
            reader.readNext(); // 跳过表头
            return reader.readAll();
        }
    }
}

2. 具备可扩展性的读取方法设计

要支持所有Person子类,采用工厂+策略模式实现,核心是基于datatype字段分发解析逻辑:

步骤1:定义解析器接口

public interface PersonParser<T extends Person> {
    T parse(String[] columns);
    String getDataType();
}

步骤2:实现子类解析器

以Employee为例:

public class EmployeeParser implements PersonParser<Employee> {
    @Override
    public Employee parse(String[] columns) {
        Employee employee = new Employee();
        // 按CSV列顺序填充属性,例如:
        // employee.setFirstname(columns[1]);
        // employee.setLastname(columns[2]);
        // ... 其他属性赋值
        return employee;
    }

    @Override
    public String getDataType() {
        return "employee";
    }
}

后续新增Person子类时,只需实现对应的解析器即可。

步骤3:工厂类管理解析器

import java.util.HashMap;
import java.util.Map;

public class PersonParserFactory {
    private static final Map<String, PersonParser<? extends Person>> parsers = new HashMap<>();

    static {
        // 注册已有的解析器
        parsers.put(new EmployeeParser().getDataType(), new EmployeeParser());
    }

    public static PersonParser<? extends Person> getParser(String dataType) {
        return parsers.get(dataType);
    }

    // 支持动态注册新解析器,增强扩展性
    public static void registerParser(PersonParser<? extends Person> parser) {
        parsers.put(parser.getDataType(), parser);
    }
}

步骤4:整合读取与解析逻辑

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class ExtensiblePersonReader {
    public static List<Person> readPersons(String filePath) throws IOException {
        List<String[]> rows = OpenCsvReader.readCsv(filePath);
        List<Person> persons = new ArrayList<>();

        for (String[] columns : rows) {
            String dataType = columns[0];
            PersonParser<? extends Person> parser = PersonParserFactory.getParser(dataType);
            if (parser != null) {
                persons.add(parser.parse(columns));
            } else {
                throw new IllegalArgumentException("不支持的数据类型:" + dataType);
            }
        }
        return persons;
    }
}

新增Person子类时,仅需实现解析器并注册到工厂,无需修改核心读取逻辑,符合开闭原则。

3. 能否将CSV数据存储到CreatePersonCommand类?

完全可以。CreatePersonCommand的dataType字段对应CSV的datatype列,其余列可作为键值对存入params集合。

实现代码示例:

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class CommandConverter {
    private static final String[] HEADERS = {
        "datatype", "firstname", "lastname", "identifier", "height", 
        "weight", "email", "hiredate", "jobposition", "salary", 
        "nameschool", "graduationyear", "major", "schoolarship"
    };

    public static List<CreatePersonCommand> convertToCommands(String filePath) throws IOException {
        List<String[]> rows = OpenCsvReader.readCsv(filePath);
        List<CreatePersonCommand> commands = new ArrayList<>();

        for (String[] columns : rows) {
            CreatePersonCommand command = new CreatePersonCommand();
            command.setDataType(columns[0]);
            
            Map<String, String> params = new HashMap<>();
            for (int i = 1; i < HEADERS.length; i++) {
                if (!"null".equals(columns[i])) {
                    params.put(HEADERS[i], columns[i]);
                }
            }
            command.setParams(params);
            commands.add(command);
        }
        return commands;
    }
}

这种方式无需关注具体Person子类,仅需按原始结构存储数据,后续可根据dataType做进一步转换,灵活性较强。

内容的提问来源于stack exchange,提问作者Mieciu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 16:13:11