Reputation: 2169
I'm trying to get a CSV from some data retrieved by Oracle. I have just to write the csv, using the result of the query as column of csv. This is my code:
// get data
final List<myDto> dataCsv = myDao.getdata();
StringWriter writer = new StringWriter();
CSVWriter csvWriter = new CSVWriter(writer,';');
List<String[]> result = toStringArray(dataCsv);
csvWriter.writeAll(result);
csvWriter.close();
return Response.ok(result).header("Content-Disposition", "attachment; filename=" + fileName).build();`
Obviously it can't find toStringArray()
. But have I to build it? Do I really need it? How do I have to edit the edit to get it working?
Upvotes: 1
Views: 1979
Reputation: 338326
The Apache Commons CSV library can help with the chore of reading/writing CSV files. It handles several variants of the CSV format, including the one used by Oracle.
Employee.java
Let's make a class for Employee
.
package work.basil.example;
import java.util.Objects;
public class Employee {
public Integer id;
public String name, role;
public Integer salary;
public Employee ( Integer id , String name , String role , Integer salary ) {
Objects.requireNonNull( id ); // etc.
this.id = id;
this.name = name;
this.role = role;
this.salary = salary;
}
@Override
public String toString ( ) {
return "Employee{ " +
"id=" + id +
" | name='" + name + '\'' +
" | role='" + role + '\'' +
" | salary=" + salary +
" }";
}
}
Make another class to mimic retrieving your DTOs. Then we write to a CSV file.
Obviously it can't find toStringArray(). But have I to build it? Do I really need it? How do I have to edit the edit to get it working?
To answer your specific Question, there is no toStringArray
method to create field values for the CSV from your DTO object‘s member variables.
This idea of mapping input or output data with member variables of a Java object is generally known as binding.
There are sophisticated binding libraries for Java to bind your objects with XML and with JSON, JAXB and JSON-B respectively. Objects can be automatically written out to XML or JSON text, as well as “re-hydrated” back to objects when read from such XML or JSON text.
But for CSV with a simpler library such as Apache Commons CSV, we read and write each field of data individually for each object. You pass each DTO object member variable, and Commons CSV will write those values out to the CSV text with any needed encapsulating quote marks, commas, and escaping.
You can see this in the code below, in this line:
printer.printRecord( e.id , e.name , e.role , e.salary );
EmployeeIo.java
Here is the entire EmployeeIo.java
file where Io
means input-output.
package work.basil.example;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
public class EmployeeIo {
public static void main ( String[] args ) {
EmployeeIo app = new EmployeeIo();
app.doIt();
}
private void doIt ( ) {
// Mimic a collection of DTO objects coming from the database.
List < Employee > employees = new ArrayList <>( 3 );
employees.add( new Employee( 101 , "Alice" , "Boss" , 11_000 ) );
employees.add( new Employee( 102 , "Bob" , "Worker" , 12_000 ) );
employees.add( new Employee( 103 , "Carol" , "Worker" , 13_000 ) );
Path path = Paths.get( "/Users/basilbourque/Employees.csv" );
this.write( employees , path );
}
public void write ( final List < Employee > employees , final Path path ) {
try ( final CSVPrinter printer = CSVFormat.ORACLE.withHeader( "Id" , "Name" , "Role" , "Salary" ).print( path , StandardCharsets.UTF_8 ) ; ) {
for ( Employee e : employees ) {
printer.printRecord( e.id , e.name , e.role , e.salary );
}
} catch ( IOException e ) {
e.printStackTrace();
}
}
}
When run, we produce a file.
Upvotes: 1
Reputation: 6473
If you just follow the example from the link that you've given, you'll see what they're doing...
private static List<String[]> toStringArray(List<Employee> emps) {
List<String[]> records = new ArrayList<String[]>();
//add header record
records.add(new String[]{"ID","Name","Role","Salary"});
Iterator<Employee> it = emps.iterator();
while(it.hasNext()){
Employee emp = it.next();
records.add(new String[]{emp.getId(),emp.getName(),emp.getRole(),emp.getSalary()});
}
return records;
}
Essentially, you need to build a List of String[]. Each String[] represents a single line of data for the CSV, with each element of the array being a value. So, yes, you need to build a List from your data model and pass it to the CSVWriter's writeAll() method.
The first String[] in the list is the column headers for the CSV. The subsequent String arrays are the data itself.
Upvotes: 2