基于索引映射CSV指定列到POJO属性的技术实现求助
Let's tackle your problem step by step—first fixing the OpenCSV column-skipping issue, then showing how to implement dynamic index-to-property mapping with univocity.
Fixing the OpenCSV Column Skipping Issue
The root problem in your original OpenCSV code is that you’re passing attribute names in the order of your JSON mappings, but ColumnPositionMappingStrategy expects an array where the array index directly corresponds to the CSV column index. For example, if you want CSV column 7 to map to iPAddress, the 7th position in the array must be iPAddress—not just adding it to the list in arbitrary order.
Here's the corrected approach:
- Find the maximum column index from your mapping list to set the correct array length.
- Initialize an array where each position matches a CSV column index, filling only the positions defined in your JSON mapping (leave others as
nullto skip those columns). - Pass this properly structured array to
setColumnMapping().
Corrected OpenCSV Code
public static List<BaseDataModel> readCSVFile(String filePath, List<ColumnIndexMapping> columnIndexMappingList) { List<BaseDataModel> csvDataModels = new ArrayList<>(); File myFile = new File(filePath); // Determine the largest column index to size our mapping array correctly int maxIndex = columnIndexMappingList.stream() .mapToInt(ColumnIndexMapping::getIndex) .max() .orElse(0); // Create array where array index = CSV column index, map only specified columns String[] columnMapping = new String[maxIndex + 1]; for (ColumnIndexMapping mapping : columnIndexMappingList) { columnMapping[mapping.getIndex()] = mapping.getColumnname(); } try (FileInputStream fis = new FileInputStream(myFile)) { ColumnPositionMappingStrategy<BaseDataModel> strategy = new ColumnPositionMappingStrategy<>(); strategy.setType(BaseDataModel.class); strategy.setColumnMapping(columnMapping); CsvToBean<BaseDataModel> csvToBean = new CsvToBeanBuilder<>(new InputStreamReader(fis)) .withMappingStrategy(strategy) .build(); csvDataModels = csvToBean.parse(); } catch (Exception e) { e.printStackTrace(); } return csvDataModels; } // Usage List<ColumnIndexMapping> columnIndexMappingList = dataSourceModel.getColumnMappingStrategy(); List<BaseDataModel> dataModels = Utility.readCSVFile( file.getAbsolutePath() + File.separator + fileName, columnIndexMappingList );
This setup ensures OpenCSV maps exactly the columns you specify by index, ignoring any positions left as null.
Implementing Dynamic Mapping with Univocity
Univocity supports flexible runtime mapping via ColumnMapper, which is ideal for your JSON-based index-to-property rules. Here's how to set it up:
Step-by-Step Univocity Code
public static List<BaseDataModel> readCSVWithUnivocity(String filePath, List<ColumnIndexMapping> columnIndexMappingList) { List<BaseDataModel> dataModels = new ArrayList<>(); File csvFile = new File(filePath); // Configure parser settings CsvParserSettings settings = new CsvParserSettings(); settings.detectFormatAutomatically(); settings.setLineSeparatorDetectionEnabled(true); // Disable header extraction if your CSV doesn't use headers (adjust if needed) settings.setHeaderExtractionEnabled(false); // Create a processor to handle POJO conversion BeanProcessor<BaseDataModel> processor = new BeanProcessor<>(BaseDataModel.class); // Define dynamic index-to-property mappings ColumnMapper columnMapper = processor.getColumnMapper(); for (ColumnIndexMapping mapping : columnIndexMappingList) { columnMapper.addMapping(mapping.getColumnname()).addIndex(mapping.getIndex()); } // Parse and collect results CsvParser parser = new CsvParser(settings); parser.addProcessor(processor); try { parser.parse(new FileReader(csvFile)); dataModels = processor.getBeans(); } catch (IOException e) { e.printStackTrace(); } return dataModels; } // Usage List<ColumnIndexMapping> columnIndexMappingList = dataSourceModel.getColumnMappingStrategy(); List<BaseDataModel> dataModels = Utility.readCSVWithUnivocity( file.getAbsolutePath() + File.separator + fileName, columnIndexMappingList );
Key Univocity Notes:
- If your CSV has headers but you want to ignore them (use indexes only), keep
setHeaderExtractionEnabled(false). - The
ColumnMapperlets you link any CSV column index to a POJO property, regardless of order or skipped columns. BeanProcessorhandles converting each row to yourBaseDataModelautomatically once mappings are defined.
内容的提问来源于stack exchange,提问作者nitin tyagi

