JTinyCsvParser
JTinyCsvParser is a high-performance CSV Parser for Java 1.8. As the name implies it is a Java version of TinyCsvParser.
It makes no use of Reflection and is very easy to use and extend.
Setup
JTinyCsvParser is available in the Central Maven Repository.
You can add the following dependencies to your pom.xml to include JTinyCsvParser in your project.
<dependency>
<groupId>de.bytefish</groupId>
<artifactId>jtinycsvparser</artifactId>
<version>1.2</version>
</dependency>
Documentation
JTinyCsvParser comes with a documentation, which is located at:
Quickstart
This is only an example for the most common use of JTinyCsvParser. For more detailed information on custom formats and more advanced use-cases,
please consult the full User Guide of the official documentation.
Imagine we have list of persons in a CSV file persons.csv
with their first name, last name and birthdate. The columns are separated by
,
as column delimiter, which each line will be split at:
Philipp;Wagner;1986/05/12
Max;Musterman;2014/01/02
The corresponding domain model in our Java code might look like this.
public class Person {
private String firstName;
private String lastName;
private LocalDate BirthDate;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public LocalDate getBirthDate() {
return BirthDate;
}
public void setBirthDate(LocalDate birthDate) {
BirthDate = birthDate;
}
}
When using JTinyCsvParser you have to define the mapping between the columns in the CSV data and
the property in you domain model, which is done by implementing the class CsvMapping<TEntity>
,
where TEntity
is the class Person
.
The IObjectCreator
passed into the mapping is a functional interface, which returns a
TEntity
object. It is used to instantiate instances of the target objects, without using
the Java Reflection API in the library.
public class PersonMapping extends CsvMapping<Person> {
public PersonMapping(IObjectCreator creator) {
super(creator);
mapProperty(0, String.class, Person::setFirstName);
mapProperty(1, String.class, Person::setLastName);
mapProperty(2, LocalDate.class, Person::setBirthDate);
}
}
The method mapProperty
is used to map between the column number in the CSV file and the property in the
domain model.
Then we can use the mapping to parse the CSV data with a CsvParser
. In the CsvParserOptions
we are
defining to not skip the header and use a ,
as column delimiter. I have assumed, that the file is encoded
as UTF8
.
public class CsvParserTest {
@Test
public void testParse_readFromFile() {
CsvParserOptions options = new CsvParserOptions(false, ",");
PersonMapping mapping = new PersonMapping(() -> new Person());
CsvParser<Person> parser = new CsvParser<>(options, mapping);
Path csvFile = FileSystems.getDefault().getPath("C:\\csv", "persons.txt");
List<CsvMappingResult<Person>> result;
try (Stream<CsvMappingResult<Person>> stream = parser.readFromFile(csvFile, StandardCharsets.UTF_8)) {
result = stream.collect(Collectors.toList());
}
Assert.assertNotNull(result);
Assert.assertEquals(2, result.size());
Person person0 = result.get(0).getResult();
Assert.assertEquals("Philipp", person0.firstName);
Assert.assertEquals("Wagner", person0.lastName);
Assert.assertEquals(1986, person0.getBirthDate().getYear());
Assert.assertEquals(5, person0.getBirthDate().getMonthValue());
Assert.assertEquals(12, person0.getBirthDate().getDayOfMonth());
Person person1 = result.get(1).getResult();
Assert.assertEquals("Max", person1.firstName);
Assert.assertEquals("Musterman", person1.lastName);
Assert.assertEquals(2000, person1.getBirthDate().getYear());
Assert.assertEquals(1, person1.getBirthDate().getMonthValue());
Assert.assertEquals(7, person1.getBirthDate().getDayOfMonth());
}
}
Reading From a String
Reading from a string is possible with the :code:CsvParser.readFromString
method.
public class CsvParserTest {
@Test
public void testParse_ReadFromString() throws Exception {
CsvParserOptions options = new CsvParserOptions(false, ",");
PersonMapping mapping = new PersonMapping(() -> new Person());
CsvParser<Person> parser = new CsvParser<>(options, mapping);
String lineSeparator = System.getProperty("line.separator");
String csvData = "Philipp,Wagner,1986-05-12" + lineSeparator + "Max,Musterman,2000-01-07";
List<CsvMappingResult<Person>> result = parser.readFromString(csvData, new CsvReaderOptions(lineSeparator))
.collect(Collectors.toList());
Assert.assertNotNull(result);
Assert.assertEquals(2, result.size());
Person person0 = result.get(0).getResult();
Assert.assertEquals("Philipp", person0.firstName);
Assert.assertEquals("Wagner", person0.lastName);
Assert.assertEquals(1986, person0.getBirthDate().getYear());
Assert.assertEquals(5, person0.getBirthDate().getMonthValue());
Assert.assertEquals(12, person0.getBirthDate().getDayOfMonth());
Person person1 = result.get(1).getResult();
Assert.assertEquals("Max", person1.firstName);
Assert.assertEquals("Musterman", person1.lastName);
Assert.assertEquals(2000, person1.getBirthDate().getYear());
Assert.assertEquals(1, person1.getBirthDate().getMonthValue());
Assert.assertEquals(7, person1.getBirthDate().getDayOfMonth());
}
}