概览
1. 什么叫做CSV
Comma-Separated Value ([卡门 赛婆乱提的]逗号分隔)(CSV),因分隔符没有严格的要求,可以使用逗号,也可以使用其他字符(如制表符\t,分号等),所以CSV也被称为逗号分隔或者其他字符分隔值。csv文件是使用纯文本来存储表格数据(只能存储文本,不能存储二进制)。
OpenCSV
package com.mkyong.io.csv.opencsv;
import com.opencsv.CSVReader;
import com.opencsv.exceptions.CsvException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
public class OpenCsvExample {
public static void main(String[] args) throws IOException, CsvException {
String fileName = "c:\\test\\csv\\country.csv";
try (CSVReader reader = new CSVReader(new FileReader(fileName))) {
List<String[]> r = reader.readAll();
r.forEach(x -> System.out.println(Arrays.toString(x)));
}
}
}
List<String[]> collect =
Files.lines(Paths.get("c:\\test\\csv\\country.csv"))
.map(line -> line.split(","))
.collect(Collectors.toList());
// Java code to illustrate reading a
// all data at once
public static void readAllDataAtOnce(String file)
{
try {
// Create an object of file reader
// class with CSV file as a parameter.
FileReader filereader = new FileReader(file);
// create csvReader object and skip first Line
CSVReader csvReader = new CSVReaderBuilder(filereader)
.withSkipLines(1)
.build();
List<String[]> allData = csvReader.readAll();
// print Data
for (String[] row : allData) {
for (String cell : row) {
System.out.print(cell + "\t");
}
System.out.println();
}
}
catch (Exception e) {
e.printStackTrace();
}
}
// Java code to illustrate
// Reading CSV File with different separator
public static void readDataFromCustomSeparator(String file)
{
try {
// Create an object of file reader class with CSV file as a parameter.
FileReader filereader = new FileReader(file);
// create csvParser object with
// custom separator semi-colon
CSVParser parser = new CSVParserBuilder().withSeparator(';').build();
// create csvReader object with parameter
// filereader and parser
CSVReader csvReader = new CSVReaderBuilder(filereader)
.withCSVParser(parser)
.build();
// Read all data at once
List<String[]> allData = csvReader.readAll();
// Print Data.
for (String[] row : allData) {
for (String cell : row) {
System.out.print(cell + "\t");
}
System.out.println();
}
}
catch (Exception e) {
e.printStackTrace();
}
}
每次读一行
// Java program to illustrate reading
// two CSV files
// with different separators
import java.io.FileReader;
import java.util.List;
import com.opencsv.*;
public class ReadCSVData {
private static final String CSV_FILE_PATH
= "D:\\EclipseWorkSpace\\CSVOperations\\results.csv";
private static final String CSV_FILE_CUSTOM_SEPARATOR
= "D:\\EclipseWorkSpace\\CSVOperations\\results_semicolon_Separator.csv";
public static void main(String[] args)
{
System.out.println("Read Data Line by Line With Header \n");
readDataLineByLine(CSV_FILE_PATH);
System.out.println("_______________________________________________");
System.out.println("Read All Data at Once and Hide the Header also \n");
readAllDataAtOnce(CSV_FILE_PATH);
System.out.println("_______________________________________________");
System.out.println("Custom Separator here semi-colon\n");
readDataFromCustomSeparator(CSV_FILE_CUSTOM_SEPARATOR);
System.out.println("_______________________________________________");
}
public static void readDataLineByLine(String file)
{
try {
// Create an object of filereader class
// with CSV file as a parameter.
FileReader filereader = new FileReader(file);
// create csvReader object passing
// filereader as parameter
CSVReader csvReader = new CSVReader(filereader);
String[] nextRecord;
// we are going to read data line by line
while ((nextRecord = csvReader.readNext()) != null) {
for (String cell : nextRecord) {
System.out.print(cell + "\t");
}
System.out.println();
}
}
catch (Exception e) {
e.printStackTrace();
}
}
public static void readAllDataAtOnce(String file)
{
try {
// Create an object of filereader class
// with CSV file as a parameter.
FileReader filereader = new FileReader(file);
// create csvReader object
// and skip first Line
CSVReader csvReader = new CSVReaderBuilder(filereader)
.withSkipLines(1)
.build();
List<String[]> allData = csvReader.readAll();
// print Data
for (String[] row : allData) {
for (String cell : row) {
System.out.print(cell + "\t");
}
System.out.println();
}
}
catch (Exception e) {
e.printStackTrace();
}
}
public static void readDataFromCustomSeparator(String file)
{
try {
// Create object of filereader
// class with csv file as parameter.
FileReader filereader = new FileReader(file);
// create csvParser object with
// custom separator semi-colon
CSVParser parser = new CSVParserBuilder().withSeparator(';').build();
// create csvReader object with
// parameter filereader and parser
CSVReader csvReader = new CSVReaderBuilder(filereader)
.withCSVParser(parser)
.build();
// Read all data at once
List<String[]> allData = csvReader.readAll();
// print Data
for (String[] row : allData) {
for (String cell : row) {
System.out.print(cell + "\t");
}
System.out.println();
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
pom.xml
<!-- csv文件解析依赖 -->
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>5.4</version>
</dependency>
手动解析CSV文件
// 析csv文件并转成bean(方法一)
public static List<CsvFile> getCsvDataMethod1(MultipartFile file) {
ArrayList<CsvFile> csvFileList = new ArrayList<>();
InputStreamReader in = null;
String s = null;
try {
in = new InputStreamReader(file.getInputStream(), "utf-8");
BufferedReader bufferedReader = new BufferedReader(in);
String line = null;
while ((line = bufferedReader.readLine()) != null) {
String[] split = line.split(",");
CsvFile csvFile = new CsvFile();
csvFile.setName(splitResult(split[0]));
csvFile.setTitle(splitResult(split[1]));
csvFile.setNumber(splitResult(split[2]));
csvFile.setType(splitResult(split[3]));
csvFile.setPersonnel(splitResult(split[4]));
csvFile.setTime(splitResult(split[5]));
csvFileList.add(csvFile);
}
} catch (IOException e) {
e.printStackTrace();
}
return csvFileList;
}
去重引号“”
private static String splitResult(String once) {
String result = "";
for (int i = 0; i < once.length(); i++) {
if (once.charAt(i) != '"') {
result += once.charAt(i);
}
}
return result;
}
openCSV解析CSV文件
/**
* 解析csv文件并转成bean(方法二)
*
* @param file csv文件
* @return 数组
*/
public static List<String[]> getCsvDataMethod2(MultipartFile file) {
List<String[]> list = new ArrayList<String[]>();
int i = 0;
try {
CSVReader csvReader = new CSVReaderBuilder(
new BufferedReader(
new InputStreamReader(file.getInputStream(), "utf-8"))).build();
Iterator<String[]> iterator = csvReader.iterator();
while (iterator.hasNext()) {
String[] next = iterator.next();
//去除第一行的表头,从第二行开始
if (i >= 1) {
list.add(next);
}
i++;
}
return list;
} catch (Exception e) {
System.out.println("CSV文件读取异常");
return list;
}
}
openCSV解析CSV文件(结果为实体类)
工具类
/**
* 解析csv文件并转成bean(方法三)
*
* @param file csv文件
* @param clazz 类
* @param <T> 泛型
* @return 泛型bean集合
*/
public static <T> List<T> getCsvDataMethod3(MultipartFile file, Class<T> clazz) {
InputStreamReader in = null;
CsvToBean<T> csvToBean = null;
try {
in = new InputStreamReader(file.getInputStream(), "utf-8");
HeaderColumnNameMappingStrategy<T> strategy = new HeaderColumnNameMappingStrategy<>();
strategy.setType(clazz);
csvToBean = new CsvToBeanBuilder<T>(in).withMappingStrategy(strategy).build();
} catch (Exception e) {
logger.error("数据转化失败");
return null;
}
return csvToBean.parse();
}
实体类
import com.opencsv.bean.CsvBindByName;
import lombok.Data;
@Data
public class CsvFile {
@CsvBindByName(column = "name")
private String name;
@CsvBindByName(column = "title")
private String title;
@CsvBindByName(column = "number")
private String number;
@CsvBindByName(column = "type")
private String type;
@CsvBindByName(column = "personnel")
private String personnel;
@CsvBindByName(column = "time")
private String time;
}
整理完成的CsvUtils
import com.lydms.testopencsv.domain.CsvFile;
import com.opencsv.CSVReader;
import com.opencsv.CSVReaderBuilder;
import com.opencsv.bean.CsvToBean;
import com.opencsv.bean.CsvToBeanBuilder;
import com.opencsv.bean.HeaderColumnNameMappingStrategy;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.web.multipart.MultipartFile;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class CsvUtils {
private static final Logger logger = LogManager.getLogger(CsvUtils.class);
/**
* 解析csv文件并转成bean(方法二)
*
* @param file csv文件
* @return 数组
*/
public static List<String[]> getCsvDataMethod2(MultipartFile file) {
List<String[]> list = new ArrayList<String[]>();
int i = 0;
try {
CSVReader csvReader = new CSVReaderBuilder(
new BufferedReader(
new InputStreamReader(file.getInputStream(), "utf-8"))).build();
Iterator<String[]> iterator = csvReader.iterator();
while (iterator.hasNext()) {
String[] next = iterator.next();
//去除第一行的表头,从第二行开始
if (i >= 1) {
list.add(next);
}
i++;
}
return list;
} catch (Exception e) {
System.out.println("CSV文件读取异常");
return list;
}
}
/**
* 解析csv文件并转成bean(方法三)
*
* @param file csv文件
* @param clazz 类
* @param <T> 泛型
* @return 泛型bean集合
*/
public static <T> List<T> getCsvDataMethod3(MultipartFile file, Class<T> clazz) {
InputStreamReader in = null;
CsvToBean<T> csvToBean = null;
try {
in = new InputStreamReader(file.getInputStream(), "utf-8");
HeaderColumnNameMappingStrategy<T> strategy = new HeaderColumnNameMappingStrategy<>();
strategy.setType(clazz);
csvToBean = new CsvToBeanBuilder<T>(in).withMappingStrategy(strategy).build();
} catch (Exception e) {
logger.error("数据转化失败");
return null;
}
return csvToBean.parse();
}
/**
* 解析csv文件并转成bean(方法一)
*
* @param file
* @return
*/
public static List<CsvFile> getCsvDataMethod1(MultipartFile file) {
ArrayList<CsvFile> csvFileList = new ArrayList<>();
InputStreamReader in = null;
String s = null;
try {
in = new InputStreamReader(file.getInputStream(), "utf-8");
BufferedReader bufferedReader = new BufferedReader(in);
String line = null;
while ((line = bufferedReader.readLine()) != null) {
String[] split = line.split(",");
CsvFile csvFile = new CsvFile();
csvFile.setName(splitResult(split[0]));
csvFile.setTitle(splitResult(split[1]));
csvFile.setNumber(splitResult(split[2]));
csvFile.setType(splitResult(split[3]));
csvFile.setPersonnel(splitResult(split[4]));
csvFile.setTime(splitResult(split[5]));
csvFileList.add(csvFile);
}
} catch (IOException e) {
e.printStackTrace();
}
return csvFileList;
}
private static String splitResult(String once) {
String result = "";
for (int i = 0; i < once.length(); i++) {
if (once.charAt(i) != '"') {
result += once.charAt(i);
}
}
return result;
}
}
根据java对象生成csv文件
readCsv
public void readCsv(String finalPath) {
try {
Reader reader = new InputStreamReader(new FileInputStream(finalPath), StandardCharsets.UTF_8);
CSVReader csvReader = new CSVReaderBuilder(reader).build();
// 列名的映射
HeaderColumnNameTranslateMappingStrategy<Person> strategy =
new HeaderColumnNameTranslateMappingStrategy<>();
strategy.setType(Person.class);
Map<String, String> columnMapping = new HashMap<>();
columnMapping.put("编号", "id");
columnMapping.put("姓名", "name");
columnMapping.put("年龄", "age");
strategy.setColumnMapping(columnMapping);
CsvToBean<Person> csvToBean = new CsvToBeanBuilder(csvReader)
.withSeparator(CSVWriter.DEFAULT_SEPARATOR)
.withQuoteChar(CSVWriter.NO_QUOTE_CHARACTER)
.withMappingStrategy(strategy)
.build();
List<Person> list = csvToBean.parse();
for (Person p : list) {
System.out.println(p.toString());
}
csvReader.close();
reader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
writeCsv
public void writeCsv(List<Person> dataList, String finalPath) {
try {
Writer writer = new FileWriter(finalPath);
// 设置显示的顺序
String[] columnMapping = {"id", "name", "age"};
ColumnPositionMappingStrategy<Person> mapper =
new ColumnPositionMappingStrategy<>();
mapper.setType(Person.class);
mapper.setColumnMapping(columnMapping);
// 写表头
CSVWriter csvWriter = new CSVWriter(writer, CSVWriter.DEFAULT_SEPARATOR, CSVWriter.NO_QUOTE_CHARACTER, '\\', "\n");
String[] header = { "编号", "姓名", "年龄"};
csvWriter.writeNext(header);
StatefulBeanToCsv beanToCsv = new StatefulBeanToCsvBuilder(writer)
.withMappingStrategy(mapper)
.withQuotechar(CSVWriter.NO_QUOTE_CHARACTER)
.withSeparator(CSVWriter.DEFAULT_SEPARATOR)
.withEscapechar('\\')
.build();
beanToCsv.write(dataList);
csvWriter.close();
writer.close();
} catch (IOException e) {
e.printStackTrace();
} catch (CsvDataTypeMismatchException e) {
e.printStackTrace();
} catch (CsvRequiredFieldEmptyException e) {
e.printStackTrace();
}
System.out.println(finalPath + "数据导出成功");
}
实体
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
private Integer id;
private String name;
private Integer age;
}
测试类的方法(maven项目结构中的测试类)
finalPath 是绝对路径+文件名,请确保欲生成的文件所在目录已创建好。
@Test
void writeCsv() {
// test data
Person person0 = new Person(11, "钱多多", 18);
Person person1 = new Person(22, "王多鱼", 19);
Person person2 = new Person(33, "喜羊羊", 20);
List<Person> personList = new ArrayList<>();
personList.add(person0);
personList.add(person1);
personList.add(person2);
String finalPath = "/Users/qianshijie/Temporary/skycomm/devsyn/test.csv";
personService.writeCsv(personList, finalPath);
}
@Test
void readCsv() {
String finalPath = "/Users/qianshijie/Temporary/skycomm/devsyn/test.csv";
personService.readCsv(finalPath);
}
上述方法中,csv 文件的列名均已被替换(已不是实体类的属性名)。如果想让生成的 csv 文件列名和实体类属性名保持一致。请使用如下代码(只列举有变化的代码,未列出则代码无变动,变动已将原代码注释,以供对比):
public void writeCsv(List<Person> dataList, String finalPath) {
try {
Writer writer = new FileWriter(finalPath);
// 设置显示的顺序
String[] columnMapping = {"id", "name", "age"};
ColumnPositionMappingStrategy<Person> mapper =
new ColumnPositionMappingStrategy<>();
mapper.setType(Person.class);
mapper.setColumnMapping(columnMapping);
// 写表头
CSVWriter csvWriter = new CSVWriter(writer, CSVWriter.DEFAULT_SEPARATOR, CSVWriter.NO_QUOTE_CHARACTER, '\\', "\n");
// String[] header = { "编号", "姓名", "年龄"};
String[] header = { "id", "name", "age"};
csvWriter.writeNext(header);
StatefulBeanToCsv beanToCsv = new StatefulBeanToCsvBuilder(writer)
.withMappingStrategy(mapper)
.withQuotechar(CSVWriter.NO_QUOTE_CHARACTER)
.withSeparator(CSVWriter.DEFAULT_SEPARATOR)
.withEscapechar('\\')
.build();
beanToCsv.write(dataList);
csvWriter.close();
writer.close();
} catch (IOException e) {
e.printStackTrace();
} catch (CsvDataTypeMismatchException e) {
e.printStackTrace();
} catch (CsvRequiredFieldEmptyException e) {
e.printStackTrace();
}
System.out.println(finalPath + "数据导出成功");
}
public void readCsv(String finalPath) {
try {
Reader reader = new InputStreamReader(new FileInputStream(finalPath), StandardCharsets.UTF_8);
CSVReader csvReader = new CSVReaderBuilder(reader).build();
// 列名的映射
// HeaderColumnNameTranslateMappingStrategy<Person> strategy =
// new HeaderColumnNameTranslateMappingStrategy<>();
// strategy.setType(Person.class);
// Map<String, String> columnMapping = new HashMap<>();
// columnMapping.put("编号", "id");
// columnMapping.put("姓名", "name");
// columnMapping.put("年龄", "age");
// strategy.setColumnMapping(columnMapping);
CsvToBean<Person> csvToBean = new CsvToBeanBuilder<Person>(csvReader)
.withSeparator(CSVWriter.DEFAULT_SEPARATOR)
.withQuoteChar(CSVWriter.NO_QUOTE_CHARACTER)
// .withMappingStrategy(strategy)
.withType(Person.class)
.build();
List<Person> list = csvToBean.parse();
for (Person p : list) {
System.out.println(p.toString());
}
csvReader.close();
reader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
中文乱码问题
String filePath = "F:/test.csv";
File file = new File(filePath);
CSVReader csvReader = null;
AccountLFFChannelDto accountLFFChannelDto = new AccountLFFChannelDto();
DataInputStream in = new DataInputStream(new FileInputStream(file));
csvReader = new CSVReader(new InputStreamReader(in,"gbk"));
List<String[]> list = csvReader.readAll();
.
.
. 以下代码省略。。。
@Test
public void readCsv() throws IOException, CsvException {
try {
String filePath = "/Users/jiadongpo/Downloads/【重要】加密数据/【保密】统一权限最新数据-20220517/ry.csv";
File file = new File(filePath);
DataInputStream in = new DataInputStream(new FileInputStream(file));
CSVReader csvReader = new CSVReader(new InputStreamReader(in, "gbk"));
String[] nextRecord;
while ((nextRecord = csvReader.readNext()) != null) {
System.out.println(nextRecord[0]);
System.out.println(nextRecord[1]);
System.out.println(nextRecord[2]);
System.out.println(nextRecord[3]);
System.out.println(nextRecord[4]);
System.out.println(nextRecord[5]);
/*for (String cell : nextRecord) {
System.out.print(cell + "\t");
}*/
System.out.println();
}
} catch (Exception e) {
e.printStackTrace();
}
}
跳过前几行
CSVReader reader = new CSVReaderBuilder(inputStreamReader)
.withFieldAsNull(CSVReaderNullFieldIndicator.EMPTY_SEPARATORS)
// Skip the header
.withSkipLines(1)
.build();
String filePath = "/Users/xxx/Downloads/10_230_21_200_389.csv";
File file = new File(filePath);
DataInputStream in = new DataInputStream(new FileInputStream(file));
CSVReader csvReader = new CSVReaderBuilder(new InputStreamReader(in, "gbk")).withFieldAsNull(CSVReaderNullFieldIndicator.EMPTY_SEPARATORS)
// Skip the header
.withSkipLines(3)
.build();