Java中csv文件转换为对象
参考文章:
使用时可能会出现
Number of passed names did not match number of header fields in the file
的错误,我的解决办法是:
换注解,原来使用的是
@CsvBindByName(column = "标头")
后来使用顺序,0代表第一个
@CsvBindByPosition(position=0)
注解更改,策略也要更改
之前使用
HeaderColumnNameMappingStrategy<T> strategy = new HeaderColumnNameMappingStrategy<>();
后来使用
ColumnPositionMappingStrategy<T> strategy = new ColumnPositionMappingStrategy<>();
注意:原来有标头,使用这个请把第一个数据移除,第一个数据是标头
原因:
在使用名称对应时,如果我把原有文件修改后再次修改为原有的文件,也就是ABA,这样是可以执行的。
我直接使用原来的会报错,查看原因,原版在解析的时候莫名会多一个字段,代码就说
Number of passed names did not match number of header fields in the file
但是ABA过后就没有这个错,无奈使用了这个笨方法,换了不采用标头的方法。
如有更好的办法可以交流交流。
1.导入依赖
<!--CSV解析依赖包-->
<dependency>
<groupId>org.jumpmind.symmetric</groupId>
<artifactId>symmetric-csv</artifactId>
<version>3.5.19</version>
</dependency>
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>4.5</version>
</dependency>
2.简单实现
import com.opencsv.bean.ColumnPositionMappingStrategy;
import com.opencsv.bean.CsvToBean;
import com.opencsv.bean.CsvToBeanBuilder;
import com.opencsv.bean.HeaderColumnNameMappingStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStreamReader;
import java.util.List;
@Slf4j
public class CSVDigester<T> {
/**
* 解析csv文件并转成bean
* @param file csv文件
* @param clazz 类
* @param <T> 泛型
* @return 泛型bean集合
*/
public static <T> List<T> getCsvDataTitle(MultipartFile file, Class<T> clazz) {
InputStreamReader in = null;
try {
in = new InputStreamReader(file.getInputStream(), "gbk");
} catch (Exception e) {
log.error("读取csv文件失败!");
}
HeaderColumnNameMappingStrategy<T> strategy = new HeaderColumnNameMappingStrategy<>();
strategy.setType(clazz);
CsvToBean<T> csvToBean = new CsvToBeanBuilder<T>(in)
.withSeparator(',')
.withQuoteChar('\'')
.withMappingStrategy(strategy).build();
return csvToBean.parse();
}
/**
* 解析csv文件并转成bean
* @param file csv文件
* @param clazz 类
* @param <T> 泛型
* @return 泛型bean集合
*/
public static <T> List<T> getCsvDataNoTitle(MultipartFile file, Class<T> clazz) {
InputStreamReader in = null;
try {
in = new InputStreamReader(file.getInputStream(), "gbk");
} catch (Exception e) {
log.error("读取csv文件失败!");
}
ColumnPositionMappingStrategy<T> strategy = new ColumnPositionMappingStrategy<>();
strategy.setType(clazz);
CsvToBean<T> csvToBean = new CsvToBeanBuilder<T>(in)
.withSeparator(',')
.withQuoteChar('\'')
.withMappingStrategy(strategy).build();
return csvToBean.parse();
}
}
3.说明
在使用时 getCsvDataTitle()方法适用于有标题的,即第一排是标头,这时使用注解
@CsvBindByName(column = "标头名称")
我在使用过程中出现了
Number of passed names did not match number of header fields in the file
更换了方法getCsvDataNoTitle(),就可以了,但是注意使用
@CsvBindByPosition(position=0)
会多一行,原来有标头的那一行删除了才是真的数据。