概览

1. 什么叫做CSV

Comma-Separated Value ([卡门 赛婆乱提的]逗号分隔)(CSV),因分隔符没有严格的要求,可以使用逗号,也可以使用其他字符(如制表符\t,分号等),所以CSV也被称为逗号分隔或者其他字符分隔值。csv文件是使用纯文本来存储表格数据(只能存储文本,不能存储二进制)。

OpenCSV

  1. package com.mkyong.io.csv.opencsv;
  2. import com.opencsv.CSVReader;
  3. import com.opencsv.exceptions.CsvException;
  4. import java.io.FileReader;
  5. import java.io.IOException;
  6. import java.util.Arrays;
  7. import java.util.List;
  8. public class OpenCsvExample {
  9. public static void main(String[] args) throws IOException, CsvException {
  10. String fileName = "c:\\test\\csv\\country.csv";
  11. try (CSVReader reader = new CSVReader(new FileReader(fileName))) {
  12. List<String[]> r = reader.readAll();
  13. r.forEach(x -> System.out.println(Arrays.toString(x)));
  14. }
  15. }
  16. }
  1. List<String[]> collect =
  2. Files.lines(Paths.get("c:\\test\\csv\\country.csv"))
  3. .map(line -> line.split(","))
  4. .collect(Collectors.toList());
  1. // Java code to illustrate reading a
  2. // all data at once
  3. public static void readAllDataAtOnce(String file)
  4. {
  5. try {
  6. // Create an object of file reader
  7. // class with CSV file as a parameter.
  8. FileReader filereader = new FileReader(file);
  9. // create csvReader object and skip first Line
  10. CSVReader csvReader = new CSVReaderBuilder(filereader)
  11. .withSkipLines(1)
  12. .build();
  13. List<String[]> allData = csvReader.readAll();
  14. // print Data
  15. for (String[] row : allData) {
  16. for (String cell : row) {
  17. System.out.print(cell + "\t");
  18. }
  19. System.out.println();
  20. }
  21. }
  22. catch (Exception e) {
  23. e.printStackTrace();
  24. }
  25. }
  1. // Java code to illustrate
  2. // Reading CSV File with different separator
  3. public static void readDataFromCustomSeparator(String file)
  4. {
  5. try {
  6. // Create an object of file reader class with CSV file as a parameter.
  7. FileReader filereader = new FileReader(file);
  8. // create csvParser object with
  9. // custom separator semi-colon
  10. CSVParser parser = new CSVParserBuilder().withSeparator(';').build();
  11. // create csvReader object with parameter
  12. // filereader and parser
  13. CSVReader csvReader = new CSVReaderBuilder(filereader)
  14. .withCSVParser(parser)
  15. .build();
  16. // Read all data at once
  17. List<String[]> allData = csvReader.readAll();
  18. // Print Data.
  19. for (String[] row : allData) {
  20. for (String cell : row) {
  21. System.out.print(cell + "\t");
  22. }
  23. System.out.println();
  24. }
  25. }
  26. catch (Exception e) {
  27. e.printStackTrace();
  28. }
  29. }

每次读一行

  1. // Java program to illustrate reading
  2. // two CSV files
  3. // with different separators
  4. import java.io.FileReader;
  5. import java.util.List;
  6. import com.opencsv.*;
  7. public class ReadCSVData {
  8. private static final String CSV_FILE_PATH
  9. = "D:\\EclipseWorkSpace\\CSVOperations\\results.csv";
  10. private static final String CSV_FILE_CUSTOM_SEPARATOR
  11. = "D:\\EclipseWorkSpace\\CSVOperations\\results_semicolon_Separator.csv";
  12. public static void main(String[] args)
  13. {
  14. System.out.println("Read Data Line by Line With Header \n");
  15. readDataLineByLine(CSV_FILE_PATH);
  16. System.out.println("_______________________________________________");
  17. System.out.println("Read All Data at Once and Hide the Header also \n");
  18. readAllDataAtOnce(CSV_FILE_PATH);
  19. System.out.println("_______________________________________________");
  20. System.out.println("Custom Separator here semi-colon\n");
  21. readDataFromCustomSeparator(CSV_FILE_CUSTOM_SEPARATOR);
  22. System.out.println("_______________________________________________");
  23. }
  24. public static void readDataLineByLine(String file)
  25. {
  26. try {
  27. // Create an object of filereader class
  28. // with CSV file as a parameter.
  29. FileReader filereader = new FileReader(file);
  30. // create csvReader object passing
  31. // filereader as parameter
  32. CSVReader csvReader = new CSVReader(filereader);
  33. String[] nextRecord;
  34. // we are going to read data line by line
  35. while ((nextRecord = csvReader.readNext()) != null) {
  36. for (String cell : nextRecord) {
  37. System.out.print(cell + "\t");
  38. }
  39. System.out.println();
  40. }
  41. }
  42. catch (Exception e) {
  43. e.printStackTrace();
  44. }
  45. }
  46. public static void readAllDataAtOnce(String file)
  47. {
  48. try {
  49. // Create an object of filereader class
  50. // with CSV file as a parameter.
  51. FileReader filereader = new FileReader(file);
  52. // create csvReader object
  53. // and skip first Line
  54. CSVReader csvReader = new CSVReaderBuilder(filereader)
  55. .withSkipLines(1)
  56. .build();
  57. List<String[]> allData = csvReader.readAll();
  58. // print Data
  59. for (String[] row : allData) {
  60. for (String cell : row) {
  61. System.out.print(cell + "\t");
  62. }
  63. System.out.println();
  64. }
  65. }
  66. catch (Exception e) {
  67. e.printStackTrace();
  68. }
  69. }
  70. public static void readDataFromCustomSeparator(String file)
  71. {
  72. try {
  73. // Create object of filereader
  74. // class with csv file as parameter.
  75. FileReader filereader = new FileReader(file);
  76. // create csvParser object with
  77. // custom separator semi-colon
  78. CSVParser parser = new CSVParserBuilder().withSeparator(';').build();
  79. // create csvReader object with
  80. // parameter filereader and parser
  81. CSVReader csvReader = new CSVReaderBuilder(filereader)
  82. .withCSVParser(parser)
  83. .build();
  84. // Read all data at once
  85. List<String[]> allData = csvReader.readAll();
  86. // print Data
  87. for (String[] row : allData) {
  88. for (String cell : row) {
  89. System.out.print(cell + "\t");
  90. }
  91. System.out.println();
  92. }
  93. }
  94. catch (Exception e) {
  95. e.printStackTrace();
  96. }
  97. }
  98. }

pom.xml

  1. <!-- csv文件解析依赖 -->
  2. <dependency>
  3. <groupId>com.opencsv</groupId>
  4. <artifactId>opencsv</artifactId>
  5. <version>5.4</version>
  6. </dependency>

手动解析CSV文件

  1. // 析csv文件并转成bean(方法一)
  2. public static List<CsvFile> getCsvDataMethod1(MultipartFile file) {
  3. ArrayList<CsvFile> csvFileList = new ArrayList<>();
  4. InputStreamReader in = null;
  5. String s = null;
  6. try {
  7. in = new InputStreamReader(file.getInputStream(), "utf-8");
  8. BufferedReader bufferedReader = new BufferedReader(in);
  9. String line = null;
  10. while ((line = bufferedReader.readLine()) != null) {
  11. String[] split = line.split(",");
  12. CsvFile csvFile = new CsvFile();
  13. csvFile.setName(splitResult(split[0]));
  14. csvFile.setTitle(splitResult(split[1]));
  15. csvFile.setNumber(splitResult(split[2]));
  16. csvFile.setType(splitResult(split[3]));
  17. csvFile.setPersonnel(splitResult(split[4]));
  18. csvFile.setTime(splitResult(split[5]));
  19. csvFileList.add(csvFile);
  20. }
  21. } catch (IOException e) {
  22. e.printStackTrace();
  23. }
  24. return csvFileList;
  25. }

去重引号“”

  1. private static String splitResult(String once) {
  2. String result = "";
  3. for (int i = 0; i < once.length(); i++) {
  4. if (once.charAt(i) != '"') {
  5. result += once.charAt(i);
  6. }
  7. }
  8. return result;
  9. }

openCSV解析CSV文件

  1. /**
  2. * 解析csv文件并转成bean(方法二)
  3. *
  4. * @param file csv文件
  5. * @return 数组
  6. */
  7. public static List<String[]> getCsvDataMethod2(MultipartFile file) {
  8. List<String[]> list = new ArrayList<String[]>();
  9. int i = 0;
  10. try {
  11. CSVReader csvReader = new CSVReaderBuilder(
  12. new BufferedReader(
  13. new InputStreamReader(file.getInputStream(), "utf-8"))).build();
  14. Iterator<String[]> iterator = csvReader.iterator();
  15. while (iterator.hasNext()) {
  16. String[] next = iterator.next();
  17. //去除第一行的表头,从第二行开始
  18. if (i >= 1) {
  19. list.add(next);
  20. }
  21. i++;
  22. }
  23. return list;
  24. } catch (Exception e) {
  25. System.out.println("CSV文件读取异常");
  26. return list;
  27. }
  28. }

openCSV解析CSV文件(结果为实体类)

工具类

  1. /**
  2. * 解析csv文件并转成bean(方法三)
  3. *
  4. * @param file csv文件
  5. * @param clazz 类
  6. * @param <T> 泛型
  7. * @return 泛型bean集合
  8. */
  9. public static <T> List<T> getCsvDataMethod3(MultipartFile file, Class<T> clazz) {
  10. InputStreamReader in = null;
  11. CsvToBean<T> csvToBean = null;
  12. try {
  13. in = new InputStreamReader(file.getInputStream(), "utf-8");
  14. HeaderColumnNameMappingStrategy<T> strategy = new HeaderColumnNameMappingStrategy<>();
  15. strategy.setType(clazz);
  16. csvToBean = new CsvToBeanBuilder<T>(in).withMappingStrategy(strategy).build();
  17. } catch (Exception e) {
  18. logger.error("数据转化失败");
  19. return null;
  20. }
  21. return csvToBean.parse();
  22. }

实体类

  1. import com.opencsv.bean.CsvBindByName;
  2. import lombok.Data;
  3. @Data
  4. public class CsvFile {
  5. @CsvBindByName(column = "name")
  6. private String name;
  7. @CsvBindByName(column = "title")
  8. private String title;
  9. @CsvBindByName(column = "number")
  10. private String number;
  11. @CsvBindByName(column = "type")
  12. private String type;
  13. @CsvBindByName(column = "personnel")
  14. private String personnel;
  15. @CsvBindByName(column = "time")
  16. private String time;
  17. }

整理完成的CsvUtils

  1. import com.lydms.testopencsv.domain.CsvFile;
  2. import com.opencsv.CSVReader;
  3. import com.opencsv.CSVReaderBuilder;
  4. import com.opencsv.bean.CsvToBean;
  5. import com.opencsv.bean.CsvToBeanBuilder;
  6. import com.opencsv.bean.HeaderColumnNameMappingStrategy;
  7. import org.apache.logging.log4j.LogManager;
  8. import org.apache.logging.log4j.Logger;
  9. import org.springframework.web.multipart.MultipartFile;
  10. import java.io.BufferedReader;
  11. import java.io.IOException;
  12. import java.io.InputStreamReader;
  13. import java.util.ArrayList;
  14. import java.util.Iterator;
  15. import java.util.List;
  16. public class CsvUtils {
  17. private static final Logger logger = LogManager.getLogger(CsvUtils.class);
  18. /**
  19. * 解析csv文件并转成bean(方法二)
  20. *
  21. * @param file csv文件
  22. * @return 数组
  23. */
  24. public static List<String[]> getCsvDataMethod2(MultipartFile file) {
  25. List<String[]> list = new ArrayList<String[]>();
  26. int i = 0;
  27. try {
  28. CSVReader csvReader = new CSVReaderBuilder(
  29. new BufferedReader(
  30. new InputStreamReader(file.getInputStream(), "utf-8"))).build();
  31. Iterator<String[]> iterator = csvReader.iterator();
  32. while (iterator.hasNext()) {
  33. String[] next = iterator.next();
  34. //去除第一行的表头,从第二行开始
  35. if (i >= 1) {
  36. list.add(next);
  37. }
  38. i++;
  39. }
  40. return list;
  41. } catch (Exception e) {
  42. System.out.println("CSV文件读取异常");
  43. return list;
  44. }
  45. }
  46. /**
  47. * 解析csv文件并转成bean(方法三)
  48. *
  49. * @param file csv文件
  50. * @param clazz 类
  51. * @param <T> 泛型
  52. * @return 泛型bean集合
  53. */
  54. public static <T> List<T> getCsvDataMethod3(MultipartFile file, Class<T> clazz) {
  55. InputStreamReader in = null;
  56. CsvToBean<T> csvToBean = null;
  57. try {
  58. in = new InputStreamReader(file.getInputStream(), "utf-8");
  59. HeaderColumnNameMappingStrategy<T> strategy = new HeaderColumnNameMappingStrategy<>();
  60. strategy.setType(clazz);
  61. csvToBean = new CsvToBeanBuilder<T>(in).withMappingStrategy(strategy).build();
  62. } catch (Exception e) {
  63. logger.error("数据转化失败");
  64. return null;
  65. }
  66. return csvToBean.parse();
  67. }
  68. /**
  69. * 解析csv文件并转成bean(方法一)
  70. *
  71. * @param file
  72. * @return
  73. */
  74. public static List<CsvFile> getCsvDataMethod1(MultipartFile file) {
  75. ArrayList<CsvFile> csvFileList = new ArrayList<>();
  76. InputStreamReader in = null;
  77. String s = null;
  78. try {
  79. in = new InputStreamReader(file.getInputStream(), "utf-8");
  80. BufferedReader bufferedReader = new BufferedReader(in);
  81. String line = null;
  82. while ((line = bufferedReader.readLine()) != null) {
  83. String[] split = line.split(",");
  84. CsvFile csvFile = new CsvFile();
  85. csvFile.setName(splitResult(split[0]));
  86. csvFile.setTitle(splitResult(split[1]));
  87. csvFile.setNumber(splitResult(split[2]));
  88. csvFile.setType(splitResult(split[3]));
  89. csvFile.setPersonnel(splitResult(split[4]));
  90. csvFile.setTime(splitResult(split[5]));
  91. csvFileList.add(csvFile);
  92. }
  93. } catch (IOException e) {
  94. e.printStackTrace();
  95. }
  96. return csvFileList;
  97. }
  98. private static String splitResult(String once) {
  99. String result = "";
  100. for (int i = 0; i < once.length(); i++) {
  101. if (once.charAt(i) != '"') {
  102. result += once.charAt(i);
  103. }
  104. }
  105. return result;
  106. }
  107. }

根据java对象生成csv文件

readCsv

  1. public void readCsv(String finalPath) {
  2. try {
  3. Reader reader = new InputStreamReader(new FileInputStream(finalPath), StandardCharsets.UTF_8);
  4. CSVReader csvReader = new CSVReaderBuilder(reader).build();
  5. // 列名的映射
  6. HeaderColumnNameTranslateMappingStrategy<Person> strategy =
  7. new HeaderColumnNameTranslateMappingStrategy<>();
  8. strategy.setType(Person.class);
  9. Map<String, String> columnMapping = new HashMap<>();
  10. columnMapping.put("编号", "id");
  11. columnMapping.put("姓名", "name");
  12. columnMapping.put("年龄", "age");
  13. strategy.setColumnMapping(columnMapping);
  14. CsvToBean<Person> csvToBean = new CsvToBeanBuilder(csvReader)
  15. .withSeparator(CSVWriter.DEFAULT_SEPARATOR)
  16. .withQuoteChar(CSVWriter.NO_QUOTE_CHARACTER)
  17. .withMappingStrategy(strategy)
  18. .build();
  19. List<Person> list = csvToBean.parse();
  20. for (Person p : list) {
  21. System.out.println(p.toString());
  22. }
  23. csvReader.close();
  24. reader.close();
  25. } catch (FileNotFoundException e) {
  26. e.printStackTrace();
  27. } catch (IOException e) {
  28. e.printStackTrace();
  29. }
  30. }

writeCsv

  1. public void writeCsv(List<Person> dataList, String finalPath) {
  2. try {
  3. Writer writer = new FileWriter(finalPath);
  4. // 设置显示的顺序
  5. String[] columnMapping = {"id", "name", "age"};
  6. ColumnPositionMappingStrategy<Person> mapper =
  7. new ColumnPositionMappingStrategy<>();
  8. mapper.setType(Person.class);
  9. mapper.setColumnMapping(columnMapping);
  10. // 写表头
  11. CSVWriter csvWriter = new CSVWriter(writer, CSVWriter.DEFAULT_SEPARATOR, CSVWriter.NO_QUOTE_CHARACTER, '\\', "\n");
  12. String[] header = { "编号", "姓名", "年龄"};
  13. csvWriter.writeNext(header);
  14. StatefulBeanToCsv beanToCsv = new StatefulBeanToCsvBuilder(writer)
  15. .withMappingStrategy(mapper)
  16. .withQuotechar(CSVWriter.NO_QUOTE_CHARACTER)
  17. .withSeparator(CSVWriter.DEFAULT_SEPARATOR)
  18. .withEscapechar('\\')
  19. .build();
  20. beanToCsv.write(dataList);
  21. csvWriter.close();
  22. writer.close();
  23. } catch (IOException e) {
  24. e.printStackTrace();
  25. } catch (CsvDataTypeMismatchException e) {
  26. e.printStackTrace();
  27. } catch (CsvRequiredFieldEmptyException e) {
  28. e.printStackTrace();
  29. }
  30. System.out.println(finalPath + "数据导出成功");
  31. }

实体

  1. @Data
  2. @AllArgsConstructor
  3. @NoArgsConstructor
  4. public class Person {
  5. private Integer id;
  6. private String name;
  7. private Integer age;
  8. }

测试类的方法(maven项目结构中的测试类)

finalPath 是绝对路径+文件名,请确保欲生成的文件所在目录已创建好。

  1. @Test
  2. void writeCsv() {
  3. // test data
  4. Person person0 = new Person(11, "钱多多", 18);
  5. Person person1 = new Person(22, "王多鱼", 19);
  6. Person person2 = new Person(33, "喜羊羊", 20);
  7. List<Person> personList = new ArrayList<>();
  8. personList.add(person0);
  9. personList.add(person1);
  10. personList.add(person2);
  11. String finalPath = "/Users/qianshijie/Temporary/skycomm/devsyn/test.csv";
  12. personService.writeCsv(personList, finalPath);
  13. }
  14. @Test
  15. void readCsv() {
  16. String finalPath = "/Users/qianshijie/Temporary/skycomm/devsyn/test.csv";
  17. personService.readCsv(finalPath);
  18. }

上述方法中,csv 文件的列名均已被替换(已不是实体类的属性名)。如果想让生成的 csv 文件列名和实体类属性名保持一致。请使用如下代码(只列举有变化的代码,未列出则代码无变动,变动已将原代码注释,以供对比):

  1. public void writeCsv(List<Person> dataList, String finalPath) {
  2. try {
  3. Writer writer = new FileWriter(finalPath);
  4. // 设置显示的顺序
  5. String[] columnMapping = {"id", "name", "age"};
  6. ColumnPositionMappingStrategy<Person> mapper =
  7. new ColumnPositionMappingStrategy<>();
  8. mapper.setType(Person.class);
  9. mapper.setColumnMapping(columnMapping);
  10. // 写表头
  11. CSVWriter csvWriter = new CSVWriter(writer, CSVWriter.DEFAULT_SEPARATOR, CSVWriter.NO_QUOTE_CHARACTER, '\\', "\n");
  12. // String[] header = { "编号", "姓名", "年龄"};
  13. String[] header = { "id", "name", "age"};
  14. csvWriter.writeNext(header);
  15. StatefulBeanToCsv beanToCsv = new StatefulBeanToCsvBuilder(writer)
  16. .withMappingStrategy(mapper)
  17. .withQuotechar(CSVWriter.NO_QUOTE_CHARACTER)
  18. .withSeparator(CSVWriter.DEFAULT_SEPARATOR)
  19. .withEscapechar('\\')
  20. .build();
  21. beanToCsv.write(dataList);
  22. csvWriter.close();
  23. writer.close();
  24. } catch (IOException e) {
  25. e.printStackTrace();
  26. } catch (CsvDataTypeMismatchException e) {
  27. e.printStackTrace();
  28. } catch (CsvRequiredFieldEmptyException e) {
  29. e.printStackTrace();
  30. }
  31. System.out.println(finalPath + "数据导出成功");
  32. }
  1. public void readCsv(String finalPath) {
  2. try {
  3. Reader reader = new InputStreamReader(new FileInputStream(finalPath), StandardCharsets.UTF_8);
  4. CSVReader csvReader = new CSVReaderBuilder(reader).build();
  5. // 列名的映射
  6. // HeaderColumnNameTranslateMappingStrategy<Person> strategy =
  7. // new HeaderColumnNameTranslateMappingStrategy<>();
  8. // strategy.setType(Person.class);
  9. // Map<String, String> columnMapping = new HashMap<>();
  10. // columnMapping.put("编号", "id");
  11. // columnMapping.put("姓名", "name");
  12. // columnMapping.put("年龄", "age");
  13. // strategy.setColumnMapping(columnMapping);
  14. CsvToBean<Person> csvToBean = new CsvToBeanBuilder<Person>(csvReader)
  15. .withSeparator(CSVWriter.DEFAULT_SEPARATOR)
  16. .withQuoteChar(CSVWriter.NO_QUOTE_CHARACTER)
  17. // .withMappingStrategy(strategy)
  18. .withType(Person.class)
  19. .build();
  20. List<Person> list = csvToBean.parse();
  21. for (Person p : list) {
  22. System.out.println(p.toString());
  23. }
  24. csvReader.close();
  25. reader.close();
  26. } catch (FileNotFoundException e) {
  27. e.printStackTrace();
  28. } catch (IOException e) {
  29. e.printStackTrace();
  30. }
  31. }

中文乱码问题

  1. String filePath = "F:/test.csv";
  2. File file = new File(filePath);
  3. CSVReader csvReader = null;
  4. AccountLFFChannelDto accountLFFChannelDto = new AccountLFFChannelDto();
  5. DataInputStream in = new DataInputStream(new FileInputStream(file));
  6. csvReader = new CSVReader(new InputStreamReader(in,"gbk"));
  7. List<String[]> list = csvReader.readAll();
  8. .
  9. .
  10. . 以下代码省略。。。
  1. @Test
  2. public void readCsv() throws IOException, CsvException {
  3. try {
  4. String filePath = "/Users/jiadongpo/Downloads/【重要】加密数据/【保密】统一权限最新数据-20220517/ry.csv";
  5. File file = new File(filePath);
  6. DataInputStream in = new DataInputStream(new FileInputStream(file));
  7. CSVReader csvReader = new CSVReader(new InputStreamReader(in, "gbk"));
  8. String[] nextRecord;
  9. while ((nextRecord = csvReader.readNext()) != null) {
  10. System.out.println(nextRecord[0]);
  11. System.out.println(nextRecord[1]);
  12. System.out.println(nextRecord[2]);
  13. System.out.println(nextRecord[3]);
  14. System.out.println(nextRecord[4]);
  15. System.out.println(nextRecord[5]);
  16. /*for (String cell : nextRecord) {
  17. System.out.print(cell + "\t");
  18. }*/
  19. System.out.println();
  20. }
  21. } catch (Exception e) {
  22. e.printStackTrace();
  23. }
  24. }

跳过前几行

  1. CSVReader reader = new CSVReaderBuilder(inputStreamReader)
  2. .withFieldAsNull(CSVReaderNullFieldIndicator.EMPTY_SEPARATORS)
  3. // Skip the header
  4. .withSkipLines(1)
  5. .build();
  1. String filePath = "/Users/xxx/Downloads/10_230_21_200_389.csv";
  2. File file = new File(filePath);
  3. DataInputStream in = new DataInputStream(new FileInputStream(file));
  4. CSVReader csvReader = new CSVReaderBuilder(new InputStreamReader(in, "gbk")).withFieldAsNull(CSVReaderNullFieldIndicator.EMPTY_SEPARATORS)
  5. // Skip the header
  6. .withSkipLines(3)
  7. .build();