java - 如何在打开的 csv 中获取并验证 csv header ?

标签 java spring-boot opencsv

我想从 csv 文件中获取标题。如果我不使用这个skipLines,那么我将在0索引数组处获得标题。但我想使用 HeaderColumnNameMappingStrategy 直接获取标题,但它不适用于我的代码。

我还想验证标题列列表(例如 csv 不允许包含额外的列)

我还检查了这个How to validate the csv headers using opencsv但这对我没有帮助。

@SuppressWarnings({ "unchecked", "rawtypes" })
public Map<String, Object> handleStockFileUpload(MultipartFile file, Long customerId) {
    Map<String, Object> responseMap = new HashMap<>();
    responseMap.put("datamap", "");
    responseMap.put("errormap", "");
    responseMap.put("errorkeys", "");

    List<Map<String, Integer>> list = new ArrayList<>();
    List<StockCsvDTO> csvStockList = new ArrayList<>();

    try {
        String fileName = new SimpleDateFormat("yyyy_MM_dd_HHmmss").format(new Date()) + "_" + file.getOriginalFilename();
        responseMap.put("filename", fileName);

        File stockFile = new File(productsUploadFilePath + fileName);
        stockFile.getParentFile().mkdirs();
        FileOutputStream fos = new FileOutputStream(stockFile);
        fos.write(file.getBytes());
        fos.close();


        CsvTransfer csvTransfer = new CsvTransfer();


        ColumnPositionMappingStrategy ms = new ColumnPositionMappingStrategy();
        ms.setType(StockCsv.class);

        Reader reader = Files.newBufferedReader(Paths.get(productsUploadFilePath + fileName));
        CSVReader csvReader =  new CSVReader(reader);

        CsvToBean cb = new CsvToBeanBuilder(reader)
          .withType(StockCsv.class)
          .withMappingStrategy(ms)
          .withSkipLines(1)
          .build();

       csvTransfer.setCsvList(cb.parse());
       reader.close();


       csvStockList = csvTransfer.getCsvList();

    } catch (Exception e) {
        e.printStackTrace();
        responseMap.put("status", "servererror");
    }

     responseMap.put("datamap", csvStockList);

    return responseMap;
}

最佳答案

我找到了以下解决方案:

  1. 将 @CsvBindByName 与 HeaderColumnNameMappingStrategy 结合使用,例如使用 @CsvBindByName 注释您的 bean 属性:
    public static class HollywoodActor {
        private int id;
        @CsvBindByName(column = "First Name")
        private String firstName;
        @CsvBindByName(column = "Last Name")
        private String lastName;
    // getter / setter
    }
  • 添加如下方法:
  •     public class CsvParser {
    
            public <T> ParseResult<T> parseByPropertyNames(Reader csvReader, Class<T> beanClass) throws IOException {
                CSVReader reader = new CSVReaderBuilder(csvReader).withCSVParser(new 
     CSVParserBuilder().build()).build();
                CsvToBean<T> bean = new CsvToBean();
                HeaderColumnNameMappingStrategy<T> mappingStrategy = new HeaderColumnNameMappingStrategy();
                mappingStrategy.setType(beanClass);
                bean.setMappingStrategy(mappingStrategy);
                bean.setCsvReader(reader);
                List<T> beans = bean.parse();
                return new CsvParseResult<>(mappingStrategy.generateHeader(), beans);
            }
    
    

    并且不要忘记添加公共(public)类 ParseResult

        public class ParseResult <T> {
          private final String[] headers;
          private final List<T> lines;
          // all-args constructor & getters
        }
    
  • 在您的代码中使用它们:
  •     String csv = "Id,First Name,Last Name\n" + "1, \"Johnny\", \"Depp\"\n" + "2, \"Al\", \"Pacino\"";
        CsvParseResult<HollywoodActor> parseResult = parser
                    .parseByPropertyNames(new InputStreamReader(new ByteArrayInputStream(csv.getBytes(StandardCharsets.UTF_8), HollywoodActor.class)));
    
  • 从 ParseResult.headers 中,您可以获取 .csv 文件中的实际 header 。只需将它们与预期进行比较即可。
  • 希望有帮助!

    关于java - 如何在打开的 csv 中获取并验证 csv header ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56056890/

    相关文章:

    java - Jsoup:如何将包含 HTML 的字符串转换为 XHTML 文档?

    java - 如何使用文件 channel 作为参数来写入对象

    java - Spring Boot 2.1 : Not loading property from application-test. yml

    java - Apache 通用 CSV 格式化程序 : IOException: invalid char between encapsulated token and delimiter

    java - 如何创建动态对象列表

    java - 线程 "main"java.lang.NoClassDefFoundError : io/netty/util/concurrent/DefaultThreadFactory 中出现异常

    Java迭代: Hashtable vs HashMap

    java - 安装适用于 Java 的 openCSV。我该如何处理 .gz 文件?

    spring-boot - 开发占地面积更小的Spring Boot应用程序

    java - 在 JAXB 中自动添加根元素