I want to write a Object into CSV file.
For XML we have XStream like this
So if i want to convert object to CSV do we have any such library ?
EDIT: I w
For easy CSV access, there is a library called OpenCSV. It really ease access to CSV file content.
EDIT
According to your update, I consider all previous replies as incorrect (due to their low-levelness). You can then go a completely diffferent way, the hibernate way, in fact !
By using the CsvJdbc driver, you can load your CSV files as JDBC data source, and then directly map your beans to this datasource.
I would have talked to you about CSVObjects, but as the site seems broken, I fear the lib is unavailable nowadays.
I wrote a simple class that uses OpenCSV
and has two static public
methods.
static public File toCSVFile(Object object, String path, String name) {
File pathFile = new File(path);
pathFile.mkdirs();
File returnFile = new File(path + name);
try {
CSVWriter writer = new CSVWriter(new FileWriter(returnFile));
writer.writeNext(new String[]{"Member Name in Code", "Stored Value", "Type of Value"});
for (Field field : object.getClass().getDeclaredFields()) {
writer.writeNext(new String[]{field.getName(), field.get(object).toString(), field.getType().getName()});
}
writer.flush();
writer.close();
return returnFile;
} catch (IOException e) {
Log.e("EasyStorage", "Easy Storage toCSVFile failed.", e);
return null;
} catch (IllegalAccessException e) {
Log.e("EasyStorage", "Easy Storage toCSVFile failed.", e);
return null;
}
}
static public void fromCSVFile(Object object, File file) {
try {
CSVReader reader = new CSVReader(new FileReader(file));
String[] nextLine = reader.readNext(); // Ignore the first line.
while ((nextLine = reader.readNext()) != null) {
if (nextLine.length >= 2) {
try {
Field field = object.getClass().getDeclaredField(nextLine[0]);
Class<?> rClass = field.getType();
if (rClass == String.class) {
field.set(object, nextLine[1]);
} else if (rClass == int.class) {
field.set(object, Integer.parseInt(nextLine[1]));
} else if (rClass == boolean.class) {
field.set(object, Boolean.parseBoolean(nextLine[1]));
} else if (rClass == float.class) {
field.set(object, Float.parseFloat(nextLine[1]));
} else if (rClass == long.class) {
field.set(object, Long.parseLong(nextLine[1]));
} else if (rClass == short.class) {
field.set(object, Short.parseShort(nextLine[1]));
} else if (rClass == double.class) {
field.set(object, Double.parseDouble(nextLine[1]));
} else if (rClass == byte.class) {
field.set(object, Byte.parseByte(nextLine[1]));
} else if (rClass == char.class) {
field.set(object, nextLine[1].charAt(0));
} else {
Log.e("EasyStorage", "Easy Storage doesn't yet support extracting " + rClass.getSimpleName() + " from CSV files.");
}
} catch (NoSuchFieldException e) {
Log.e("EasyStorage", "Easy Storage fromCSVFile failed.", e);
} catch (IllegalAccessException e) {
Log.e("EasyStorage", "Easy Storage fromCSVFile failed.", e);
}
} // Close if (nextLine.length >= 2)
} // Close while ((nextLine = reader.readNext()) != null)
} catch (FileNotFoundException e) {
Log.e("EasyStorage", "Easy Storage fromCSVFile failed.", e);
} catch (IOException e) {
Log.e("EasyStorage", "Easy Storage fromCSVFile failed.", e);
} catch (IllegalArgumentException e) {
Log.e("EasyStorage", "Easy Storage fromCSVFile failed.", e);
}
}
I think with some simple recursion these methods could be modified to handle any Java object, but for me this was adequate.
You can use gererics to work for any class
public class FileUtils<T> {
public String createReport(String filePath, List<T> t) {
if (t.isEmpty()) {
return null;
}
List<String> reportData = new ArrayList<String>();
addDataToReport(t.get(0), reportData, 0);
for (T k : t) {
addDataToReport(k, reportData, 1);
}
return !dumpReport(filePath, reportData) ? null : filePath;
}
public static Boolean dumpReport(String filePath, List<String> lines) {
Boolean isFileCreated = false;
String[] dirs = filePath.split(File.separator);
String baseDir = "";
for (int i = 0; i < dirs.length - 1; i++) {
baseDir += " " + dirs[i];
}
baseDir = baseDir.replace(" ", "/");
File base = new File(baseDir);
base.mkdirs();
File file = new File(filePath);
try {
if (!file.exists())
file.createNewFile();
} catch (Exception e) {
e.printStackTrace();
return isFileCreated;
}
try (BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(file), System.getProperty("file.encoding")))) {
for (String line : lines) {
writer.write(line + System.lineSeparator());
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
void addDataToReport(T t, List<String> reportData, int index) {
String[] jsonObjectAsArray = new Gson().toJson(t).replace("{", "").replace("}", "").split(",\"");
StringBuilder row = new StringBuilder();
for (int i = 0; i < jsonObjectAsArray.length; i++) {
String str = jsonObjectAsArray[i];
str = str.replaceFirst(":", "_").split("_")[index];
if (i == 0) {
if (str != null) {
row.append(str.replace("\"", ""));
} else {
row.append("N/A");
}
} else {
if (str != null) {
row.append(", " + str.replace("\"", ""));
} else {
row.append(", N/A");
}
}
}
reportData.add(row.toString());
}
Two options I just ran into:
First, serialization is writing the object to a file 'as it is'. AFAIK, you cannot choose file formats and all. The serialized object (in a file) has its own 'file format'
If you want to write the contents of an object (or a list of objects) to a CSV file, you can do it yourself, it should not be complex.
Looks like Java CSV Library can do this, but I have not tried this myself.
EDIT: See following sample. This is by no way foolproof, but you can build on this.
//European countries use ";" as
//CSV separator because "," is their digit separator
private static final String CSV_SEPARATOR = ",";
private static void writeToCSV(ArrayList<Product> productList)
{
try
{
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("products.csv"), "UTF-8"));
for (Product product : productList)
{
StringBuffer oneLine = new StringBuffer();
oneLine.append(product.getId() <=0 ? "" : product.getId());
oneLine.append(CSV_SEPARATOR);
oneLine.append(product.getName().trim().length() == 0? "" : product.getName());
oneLine.append(CSV_SEPARATOR);
oneLine.append(product.getCostPrice() < 0 ? "" : product.getCostPrice());
oneLine.append(CSV_SEPARATOR);
oneLine.append(product.isVatApplicable() ? "Yes" : "No");
bw.write(oneLine.toString());
bw.newLine();
}
bw.flush();
bw.close();
}
catch (UnsupportedEncodingException e) {}
catch (FileNotFoundException e){}
catch (IOException e){}
}
This is product (getters and setters hidden for readability):
class Product
{
private long id;
private String name;
private double costPrice;
private boolean vatApplicable;
}
And this is how I tested:
public static void main(String[] args)
{
ArrayList<Product> productList = new ArrayList<Product>();
productList.add(new Product(1, "Pen", 2.00, false));
productList.add(new Product(2, "TV", 300, true));
productList.add(new Product(3, "iPhone", 500, true));
writeToCSV(productList);
}
Hope this helps.
Cheers.
Worth mentioning that the handlebar library https://github.com/jknack/handlebars.java can trivialize many transformation tasks include toCSV.