Comma-Separated Values (CSV) là một tập tin văn bản bình thường, nó lưu trữ dữ liệu theo từng cột, và chia nó bằng dấu phân cách (thường là dấu phẩy “,“).
Ví dụ:
1,US,United States 2,VN,Viet Nam 3,AU,Australia
hoặc
"1","US","United States" "2","VN","Viet Nam" "3","AU","Australia"
Trong bài hướng dẫn này, tôi sẽ giới thiệu với các bạn một số cách để ghi nội dung ra file csv, đọc/ phân tích cú pháp từ file CSV:
- Sử dụng lớp FileReader, FileWriter.
- Sử dụng thư viện Apache common CSV.
- Sử dụng thư viện OpenCSV.
Nội dung
Sử dụng lớp FileReader, FileWriter
Ví dụ ghi nội dung ra file CSV
Country.java
package com.gpcoder.csv; public class Country { private int id; private String code; private String name; public Country() { super(); } public Country(int id, String code, String name) { super(); this.id = id; this.code = code; this.name = name; } @Override public String toString() { return "Country [id=" + id + ", code=" + code + ", name=" + name + "]"; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
CsvWriterExample.java
package com.gpcoder.csv; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class CsvWriterExample { // Delimiter used in CSV file private static final String COMMA_DELIMITER = ","; private static final String NEW_LINE_SEPARATOR = "\n"; // CSV file header private static final String FILE_HEADER = "id,code,name"; public static void main(String[] args) { String fileName = "data/contries.csv"; writeCsvFile(fileName); } public static void writeCsvFile(String fileName) { // Create new Countrys objects Country country1 = new Country(1, "US", "United States"); Country country2 = new Country(2, "VN", "Viet Nam"); Country country3 = new Country(3, "AU", "Australia"); // Create a new list of Country objects List<Country> countries = new ArrayList<>(); countries.add(country1); countries.add(country2); countries.add(country3); FileWriter fileWriter = null; try { fileWriter = new FileWriter(fileName); // Write the CSV file header fileWriter.append(FILE_HEADER); // Add a new line separator after the header fileWriter.append(NEW_LINE_SEPARATOR); // Write a new Country object list to the CSV file for (Country country : countries) { fileWriter.append(String.valueOf(country.getId())); fileWriter.append(COMMA_DELIMITER); fileWriter.append(country.getCode()); fileWriter.append(COMMA_DELIMITER); fileWriter.append(country.getName()); fileWriter.append(NEW_LINE_SEPARATOR); } System.out.println("CSV file was created successfully !!!"); } catch (Exception e) { System.out.println("Error in CsvFileWriter !!!"); e.printStackTrace(); } finally { try { fileWriter.flush(); fileWriter.close(); } catch (IOException e) { System.out.println("Error while flushing/closing fileWriter !!!"); e.printStackTrace(); } } } }
Thực thi chương trình trên, một file contries.csv được tạo ra trong thư mục của project.
Ví dụ phân tích cú pháp một file CSV
CsvWriterExmaple.java
package com.gpcoder.csv; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class CsvReaderExample { private static final String COMMA_DELIMITER = ","; // Split by comma public static void main(String[] args) { BufferedReader br = null; try { String line; br = new BufferedReader(new FileReader("data/contries.csv")); // How to read file in java line by line? while ((line = br.readLine()) != null) { printContry(parseCsvLine(line)); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (br != null) br.close(); } catch (IOException crunchifyException) { crunchifyException.printStackTrace(); } } } public static List<String> parseCsvLine(String csvLine) { List<String> result = new ArrayList<String>(); if (csvLine != null) { String[] splitData = csvLine.split(COMMA_DELIMITER); for (int i = 0; i < splitData.length; i++) { result.add(splitData[i]); } } return result; } private static void printContry(List<String> country) { System.out.println( "Country [id= " + country.get(0) + ", code= " + country.get(1) + " , name=" + country.get(2) + "]"); } }
Kết quả thực thi chương trình trên:
Country [id= id, code= code , name=name] Country [id= 1, code= US , name=United States] Country [id= 2, code= VN , name=Viet Nam] Country [id= 3, code= AU , name=Australia]
Sử dụng thư viện Apache common CSV
Download thư viện OpenCSV: thêm khai báo thư viện maven vào project.
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-csv --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-csv</artifactId> <version>1.4</version> </dependency>
Ghi nội dung ra file CSV
ApacheCsvWriterExample.java
package com.gpcoder.csv; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVPrinter; public class ApacheCsvWriterExample { public static void main(String[] args) throws IOException { String csvFile = "data/data.csv"; try (BufferedWriter writer = new BufferedWriter(new FileWriter(csvFile)); CSVPrinter csvPrinter = new CSVPrinter(writer, CSVFormat.DEFAULT.withHeader("id", "code", "name"));) { csvPrinter.printRecord("1", "US", "United States"); csvPrinter.printRecord("2", "VN", "Viet Nam"); csvPrinter.printRecord("3", "AU", "Australia"); csvPrinter.flush(); } } }
Thực thi chương trình trên, một file data.csv được tạo ra trong thư mục data của project.
Ví dụ phân tích cú pháp một file CSV
ApacheCsvReaderExample.java
package com.gpcoder.csv; import java.io.FileReader; import java.io.IOException; import java.io.Reader; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVParser; import org.apache.commons.csv.CSVRecord; public class ApacheCsvReaderExample { public static void main(String[] args) throws IOException { String csvFile = "data/data.csv"; try (Reader reader = new FileReader(csvFile); CSVParser csvParser = new CSVParser(reader, CSVFormat.DEFAULT);) { Iterable<CSVRecord> csvRecords = csvParser.getRecords(); for (CSVRecord csvRecord : csvRecords) { System.out.println("Country [id= " + csvRecord.get(0) + ", code= " + csvRecord.get(1) + " , name=" + csvRecord.get(2) + "]"); } } } }
Kết quả thực thi chương trình trên:
Country [id= id, code= code , name=name] Country [id= 1, code= US , name=United States] Country [id= 2, code= VN , name=Viet Nam] Country [id= 3, code= AU , name=Australia]
ApacheCsvReaderExample2.java
package com.gpcoder.csv; import java.io.FileReader; import java.io.IOException; import java.io.Reader; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVParser; import org.apache.commons.csv.CSVRecord; /** * Reading a CSV file (Access Values by Names assigned to each column) */ public class ApacheCsvReaderExample2 { public static void main(String[] args) throws IOException { String csvFile = "data/data.csv"; try (Reader reader = new FileReader(csvFile); CSVParser csvParser = new CSVParser(reader, CSVFormat.DEFAULT .withHeader("id", "code", "name") .withIgnoreHeaderCase() .withTrim());) { for (CSVRecord csvRecord : csvParser.getRecords()) { // Accessing values by the names assigned to each column System.out.println("Country [id= " + csvRecord.get(0) + ", code= " + csvRecord.get(1) + " , name=" + csvRecord.get(2) + "]"); } } } }
Kết quả thực thi chương trình trên:
Country [id= id, code= code , name=name] Country [id= 1, code= US , name=United States] Country [id= 2, code= VN , name=Viet Nam] Country [id= 3, code= AU , name=Australia]
ApacheCsvReaderExample3.java
package com.gpcoder.csv; import java.io.FileReader; import java.io.IOException; import java.io.Reader; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVParser; import org.apache.commons.csv.CSVRecord; /** * Reading a CSV file with Header Auto-detection (Access Values by Header names) */ public class ApacheCsvReaderExample3 { public static void main(String[] args) throws IOException { String csvFile = "data/data.csv"; try (Reader reader = new FileReader(csvFile); CSVParser csvParser = new CSVParser(reader, CSVFormat.DEFAULT .withFirstRecordAsHeader() .withIgnoreHeaderCase() .withTrim());) { for (CSVRecord csvRecord : csvParser.getRecords()) { // Accessing values by Header names System.out.println("Country [id= " + csvRecord.get(0) + ", code= " + csvRecord.get(1) + " , name=" + csvRecord.get(2) + "]"); } } } }
Kết quả thực thi chương trình trên:
Country [id= 1, code= US , name=United States] Country [id= 2, code= VN , name=Viet Nam] Country [id= 3, code= AU , name=Australia]
Sử dụng thư viện OpenCSV
Download thư viện OpenCSV: thêm khai báo thư viện maven vào project.
<!-- https://mvnrepository.com/artifact/com.opencsv/opencsv --> <dependency> <groupId>com.opencsv</groupId> <artifactId>opencsv</artifactId> <version>4.1</version> </dependency>
Ghi nội dung ra file CSV
package com.gpcoder.csv; import java.io.FileWriter; import java.io.IOException; import java.io.Writer; import com.opencsv.CSVWriter; public class OpenCsvWriterExmaple { public static void main(String[] args) throws IOException { String csv = "data/data.csv"; try (Writer writer = new FileWriter(csv); CSVWriter csvWriter = new CSVWriter(writer, CSVWriter.DEFAULT_SEPARATOR, CSVWriter.NO_QUOTE_CHARACTER, CSVWriter.DEFAULT_ESCAPE_CHARACTER, CSVWriter.DEFAULT_LINE_END);) { String[] headerRecord = { "id", "code", "name" }; csvWriter.writeNext(headerRecord); csvWriter.writeNext(new String[] { "1", "US", "United States" }); csvWriter.writeNext(new String[] { "2", "VN", "Viet Nam" }); csvWriter.writeNext(new String[] { "3", "AU", "Australia" }); } } }
Thực thi chương trình trên, một file output.csv được tạo ra trong thư mục data của project.
Ví dụ phân tích cú pháp một file CSV
package com.gpcoder.csv; import java.io.FileReader; import java.io.IOException; import java.io.Reader; import com.opencsv.CSVReader; public class OpenCsvReaderExmaple { public static void main(String[] args) throws IOException { String csvFile = "data/data.csv"; try (Reader reader = new FileReader(csvFile); CSVReader csvReader = new CSVReader(reader);) { // Reading Records One by One in a String array String[] line; while ((line = csvReader.readNext()) != null) { System.out.println("Country [id= " + line[0] + ", code= " + line[1] + " , name=" + line[2] + "]"); } } } }
Kết quả thực thi chương trình trên:
Country [id= id, code= code , name=name] Country [id= 1, code= US , name=United States] Country [id= 2, code= VN , name=Viet Nam] Country [id= 3, code= AU , name=Australia]
Ví dụ map nội dung file CSV sang Java Object
Country.java
package com.gpcoder.csv; public class Country { private int id; private String code; private String name; public Country() { super(); } public Country(int id, String code, String name) { super(); this.id = id; this.code = code; this.name = name; } @Override public String toString() { return "Country [id=" + id + ", code=" + code + ", name=" + name + "]"; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
ParseCsvToBean.java
package com.gpcoder.csv; import java.io.FileNotFoundException; import java.io.FileReader; import java.util.List; import com.opencsv.bean.ColumnPositionMappingStrategy; import com.opencsv.bean.CsvToBean; import com.opencsv.bean.CsvToBeanBuilder; public class ParseCsvToBean { // the delimiter to use for separating entries private static final char DEFAULT_SEPARATOR = ','; // the character to use for quoted elements private static final char DEFAULT_QUOTE = '"'; // the line number to skip for start reading private static final int NUM_OF_LINE_SKIP = 1; public static void main(String[] args) throws FileNotFoundException { String csvFile = "data/data.csv"; parseCSVtoBean(csvFile); } public static void parseCSVtoBean(String filename) throws FileNotFoundException { ColumnPositionMappingStrategy<Country> strategy = new ColumnPositionMappingStrategy<Country>(); strategy.setType(Country.class); String[] columns = new String[] { "id", "code", "name" }; strategy.setColumnMapping(columns); CsvToBean<Country> csvToBean = new CsvToBeanBuilder<Country>(new FileReader(filename)) .withMappingStrategy(strategy) .withSeparator(DEFAULT_SEPARATOR) .withQuoteChar(DEFAULT_QUOTE) .withSkipLines(NUM_OF_LINE_SKIP) .withIgnoreLeadingWhiteSpace(true) .build(); List<Country> countries = csvToBean.parse(); for (Country country : countries) { System.out.println(country); } } }
Kết quả thực thi chương trình trên:
Country [id=1, code=US, name=United States] Country [id=2, code=VN, name=Viet Nam] Country [id=3, code=AU, name=Australia]
Ví dụ map nội dung file CSV sang Java Object sử dụng Annotation
CountryAnn.java
package com.gpcoder.csv; import com.opencsv.bean.CsvBindByPosition; public class CountryAnn { @CsvBindByPosition(position = 0) private int id; @CsvBindByPosition(position = 1) private String code; @CsvBindByPosition(position = 2) private String name; public CountryAnn() { super(); } public CountryAnn(int id, String code, String name) { super(); this.id = id; this.code = code; this.name = name; } @Override public String toString() { return "Country [id=" + id + ", code=" + code + ", name=" + name + "]"; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
ParseCsvToObjectUsingAnnotation.java
package com.gpcoder.csv; import java.io.FileReader; import java.io.IOException; import java.io.Reader; import java.util.List; import com.opencsv.bean.CsvToBean; import com.opencsv.bean.CsvToBeanBuilder; public class ParseCsvToObjectUsingAnnotation { public static void main(String[] args) throws IOException { String csvFile = "data/data.csv"; try (Reader reader = new FileReader(csvFile);) { CsvToBean<CountryAnn> csvToBean = new CsvToBeanBuilder<CountryAnn>(reader) .withType(CountryAnn.class) .withSkipLines(1) // skip header .withIgnoreLeadingWhiteSpace(true) .build(); List<CountryAnn> contries = csvToBean.parse(); for (CountryAnn contry : contries) { System.out.println(contry); } } } }
Kết quả thực thi chương trình trên:
Country [id=1, code=US, name=United States] Country [id=2, code=VN, name=Viet Nam] Country [id=3, code=AU, name=Australia]
Một số vấn đề cần lưu ý khi phân tích file CSV
Trong file CSV, thông thường có hai vấn đề:
1. Trường có chứa dấu phân cách, ví dụ: dấu phân là dấu phẩy và dữ liệu chứa dấu phẩy:
"aaa","b,bb","ccc"
2. Dấu nháy kép được sử dụng để hiển thị giá trị của cột, và dữ liệu có chứa dấu nháy kép. Để giải quyết nó, một dấu nháy kép xuất hiện bên trong một cột phải được escape bằng cách đặt nó trước nó bằng một dấu ngoặc kép khác.
Ví dụ:
"aaa","b""bb","ccc"