Có rất nhiều cách đọc file csv, nhưng đọc file như thế nào để tiện sử dụng sau này, mình chọn cách sử dụng thư viện opencsv để mapping CSV <—> POJO. Có được POJO rồi thì mình làm gì thì làm.
Note: POJO là Plain Old Java Object, 1 object bình thường như bao object khác.
Nội dung bài viết
I. Cài đặt thư viện
Đầu tiên bạn cần import lib opencsv vào trong project.
Maven:
<dependency> <groupId>com.opencsv</groupId> <artifactId>opencsv</artifactId> <version>5.4</version> </dependency>
Gradle
implementation group: 'com.opencsv', name: 'opencsv', version: '5.4'
II. Đọc file csv có header
Giả sử bạn có file data.csv
như sau:
First Name, LastName, Age, Address, Birthday giang, nguyen, 30, Hanoi,01-01-1991 lucas, owen,,,20-01-2000 nam, Do, 10, Ninh Binh,15-05-1995
Bạn cần mapping file csv này với Class tương ứng
import com.opencsv.bean.CsvBindByName; import com.opencsv.bean.CsvDate; import lombok.Data; import java.time.LocalDate; @Data public class PersonObject { @CsvBindByName(column = "First Name", required = true) (1) private String firstName; @CsvBindByName(column = "LastName") private String lastName; @CsvBindByName() private int age; @CsvBindByName() private String address; @CsvBindByName() @CsvDate(value = "dd-MM-yyyy") (2) private LocalDate birthday; }
- (1) Mapping cột “First Name” với biến firstName
- (2) Mapping date với kiểu định dạng “dd-MM-yyyy” với object LocalDate.
Test thử
@Test void name() throws FileNotFoundException { List<PersonObject> list = new CsvToBeanBuilder<PersonObject> (new FileReader("src/test/resources/data.csv")) .withType(PersonObject.class) .build().parse(); list.forEach(System.out::println); }
PersonObject(firstName=giang, lastName= nguyen, age=30, address= Hanoi, birthday=1991-01-01) PersonObject(firstName=lucas, lastName= owen, age=0, address=, birthday=2000-01-20) PersonObject(firstName=nam, lastName= Do, age=10, address= Ninh Binh, birthday=1995-05-15)
III. Đọc file csv không có header
giang,nguyen,30,Hanoi,01-01-1991 lucas,owen,1,HCM,20-01-2000 nam,Do,10,Ninh Binh,15-05-1995
Bạn cần phải mapping theo số thứ tự của cột
import com.opencsv.bean.CsvBindByPosition; import com.opencsv.bean.CsvDate; import lombok.Data; import java.time.LocalDate; @Data public class NoHeaderCsvObject { @CsvBindByPosition(position = 0) private String firstName; @CsvBindByPosition(position = 1) private String lastName; @CsvBindByPosition(position = 2) private int age; @CsvBindByPosition(position = 3) private String address; @CsvBindByPosition(position = 4) @CsvDate(value = "dd-MM-yyyy") private LocalDate birthday; }
Tương tự thì bạn cũng có thể test như sau.
@Test void name2() throws FileNotFoundException { List<NoHeaderCsvObject> list = new CsvToBeanBuilder<NoHeaderCsvObject> (new FileReader("src/test/resources/data2.csv")) .withType(NoHeaderCsvObject.class) .build().parse(); list.forEach(System.out::println); }
NoHeaderCsvObject(firstName=giang, lastName=nguyen, age=30, address=Hanoi, birthday=1991-01-01) NoHeaderCsvObject(firstName=lucas, lastName=owen, age=1, address=HCM, birthday=2000-01-20) NoHeaderCsvObject(firstName=nam, lastName=Do, age=10, address=Ninh Binh, birthday=1995-05-15)
IV. Tổng kết
Thư viện còn khá nhiều tùy biến hay ho nhưng mà mình không giới thiệu hết được (vì lười viết) nên chỉ nói 2 trường hợp cơ bản nhất thôi. Các bạn có thể đọc tiếp document của thư viện để biết thêm các trường hợp sử dụng khác.