Apache 公共 CSV 解析器

Apache commons CSV parser

如何在不中继订单的情况下从 CSV 中读取值?

即使在内部使用 .get("headerName") 阅读也依赖于顺序。有人找到更好的方法来处理这个问题吗?

csv 示例

header1,header2
1111111,2222222

您可以尝试使用 univocity-parsers 来 select 您感兴趣的列。

CsvParserSettings settings = new CsvParserSettings();
settings.selectFields("e", "d", "b", "a");

CsvParser parser = new CsvParser(settings);

//all rows will have the values of your selected headers only, in the order you defined above.
List<Record> allRecords = parser.parseAllRecords(new File("/path/to/your.csv"));

希望对您有所帮助

披露:我是这个库的作者。它是开源且免费的(Apache 2.0 许可证)

最后我自己写了逻辑将csv映射成map。虽然使用了具有非常基本功能的 apache csv 解析器。

 public List<Map<String, Object>> getMapFromCSV(MultipartFile multipartFile) {
        try {
            CSVParser parser = parseCSV(multipartFile.getInputStream());
            return getMap(parser.getRecords(), parser.getHeaderMap());
        } catch (IOException e) {
            throw new RunTimeException(e);
        }
    }

    private List<Map<String, Object>> getMap (List<CSVRecord> records, Map<String, Integer> headers) {
        Map<Integer, String> headerMap = formatHeaderMap(headers);
        List<Map<String, Object>> data = new ArrayList<>();
        for (int i = 1; i < records.size(); i++) {
            Map<String, Object> map = new HashMap<>();
            try {
                CSVRecord record = records.get(i);
                for (int j = 0; j < record.size(); j++) {
                    map.put(headerMap.get(j), record.get(j));
                }
                data.add(map);
            } catch (Exception e) {
                throw new RunTimeException(e);
            }
        }
        return data;
    }

    private Map<Integer, String> formatHeaderMap(Map<String, Integer> map) {
        Map<Integer, String> data = new HashMap<>();
        map.forEach((k , v) -> {
            data.put(v, k);
        });
        return data;
    }

    private CSVParser parseCSV(InputStream inputStream) {
        try {
            return new CSVParser(new InputStreamReader(inputStream), CSVFormat.DEFAULT
                    .withFirstRecordAsHeader()
                    .withIgnoreHeaderCase()
                    .withSkipHeaderRecord()
                    .withTrim());
        } catch (IOException e) {
            throw new RunTimeException(e);
        }
    }

我一直在努力解决这个问题并找到了解决方案!您需要指定不带任何参数的 .withHeaders() 调用,以允许库为列计算正确的索引。例如:

CSVParser.parse(inputStream, Charset.defaultCharset(), 
    CSVFormat.DEFAULT
             .withTrim()
             .withHeader() // note, do not specify any columns here
)