如何将对象序列化为CSV文件?

时间:2010-09-08 08:47:17

标签: java serialization csv object

我想将一个Object写入CSV文件。 对于XML,我们有像this一样的XStream 所以如果我想将对象转换为CSV,我们有没有这样的库?

编辑: 我想将我的Bean列表传递给一个方法,该方法应该将bean的所有字段都写入CSV。

8 个答案:

答案 0 :(得分:21)

首先,序列化是将对象“原样”写入文件。 AFAIK,您无法选择所有文件格式。序列化对象(在文件中)具有自己的“文件格式”

如果要将对象(或对象列表)的内容写入CSV文件,您可以自己完成,它不应该很复杂。

看起来Java CSV Library可以做到这一点,但我自己没试过。

编辑:请参阅以下示例。这绝不是万无一失的,但你可以在此基础上继续。

    //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){}
    }

这是产品(为了便于阅读而隐藏了getter和setter):

class Product
{
    private long id;
    private String name;
    private double costPrice;
    private boolean vatApplicable;
}

这就是我测试的方式:

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);
}

希望这有帮助。

干杯。

答案 1 :(得分:4)

为了便于CSV访问,有一个名为OpenCSV的库。它真的很容易访问CSV文件内容。

修改

根据您的更新,我认为之前的所有回复都是错误的(由于它们的低级别)。然后,您可以采用完全不同的方式,即休眠方式!

通过使用CsvJdbc驱动程序,您可以将CSV文件作为JDBC数据源加载,然后直接将bean映射到此数据源。

我会和你谈谈CSVObjects,但由于该网站似乎已被破坏,我担心现在的lib不可用。

答案 2 :(得分:4)

答案 3 :(得分:3)

有一个csv序列化器会很有趣,因为与其他序列化方法相比,它会占用最小的空间。

最接近java对象到csv的支持是spring utils project

提供的stringutils

arrayToCommaDelimitedString(Object [] arr)但它远不是一个序列化器。

这是一个简单的实用程序,它使用反射来序列化值对象

public class CSVWriter
{
private static String produceCsvData(Object[] data) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
{
    if(data.length==0)
    {
        return "";
    }

    Class classType = data[0].getClass();
    StringBuilder builder = new StringBuilder();

    Method[] methods = classType.getDeclaredMethods();

    for(Method m : methods)
    {
        if(m.getParameterTypes().length==0)
        {
            if(m.getName().startsWith("get"))
            {
                builder.append(m.getName().substring(3)).append(',');
            }
            else if(m.getName().startsWith("is"))
            {
                builder.append(m.getName().substring(2)).append(',');
            }

        }

    }
    builder.deleteCharAt(builder.length()-1);
    builder.append('\n');
    for(Object d : data)
    {
        for(Method m : methods)
        {
            if(m.getParameterTypes().length==0)
            {
                if(m.getName().startsWith("get") || m.getName().startsWith("is"))
                {
                    System.out.println(m.invoke(d).toString());
                    builder.append(m.invoke(d).toString()).append(',');
                }
            }
        }
        builder.append('\n');
    }
    builder.deleteCharAt(builder.length()-1);
    return builder.toString();
}

public static boolean generateCSV(File csvFileName,Object[] data)
{
    FileWriter fw = null;
    try
    {
        fw = new FileWriter(csvFileName);
        if(!csvFileName.exists())
            csvFileName.createNewFile();
        fw.write(produceCsvData(data));
        fw.flush();
    }
    catch(Exception e)
    {
        System.out.println("Error while generating csv from data. Error message : " + e.getMessage());
        e.printStackTrace();
        return false;
    }
    finally
    {
        if(fw!=null)
        {
            try
            {
                fw.close();
            }
            catch(Exception e)
            {
            }
            fw=null;
        }
    }
    return true;
}

}

这是一个示例值对象

public class Product {
private String name;
private double price;
private int identifier;
private boolean isVatApplicable;
public Product(String name, double price, int identifier,
        boolean isVatApplicable) {
    super();
    this.name = name;
    this.price = price;
    this.identifier = identifier;
    this.isVatApplicable = isVatApplicable;
}
public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
public double getPrice() {
    return price;
}
public void setPrice(long price) {
    this.price = price;
}
public int getIdentifier() {
    return identifier;
}
public void setIdentifier(int identifier) {
    this.identifier = identifier;
}
public boolean isVatApplicable() {
    return isVatApplicable;
}
public void setVatApplicable(boolean isVatApplicable) {
    this.isVatApplicable = isVatApplicable;
}

}

以及运行util

的代码
public class TestCSV 
{
public static void main(String... a)
{
    Product[] list = new Product[5];
    list[0] = new Product("dvd", 24.99, 967, true);
    list[1] = new Product("pen", 4.99, 162, false);
    list[2] = new Product("ipad", 624.99, 234, true);
    list[3] = new Product("crayons", 4.99,127, false);
    list[4] = new Product("laptop", 1444.99, 997, true);
    CSVWriter.generateCSV(new File("C:\\products.csv"),list);
}

}

输出:

Name    VatApplicable   Price   Identifier
dvd     true            24.99   967
pen     false           4.99    162
ipad    true            624.99  234
crayons false           4.99    127
laptop  true            1444.99 997

答案 4 :(得分:0)

我写了一个使用OpenCSV的简单类,并且有两个static public方法。

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);
    }
}

我认为通过一些简单的递归可以修改这些方法来处理任何Java对象,但对我来说这已经足够了。

答案 5 :(得分:0)

虽然回复非常晚,但我遇到了在各种项目中将java entites导出为CSV,EXCEL等的问题,我们需要在UI上提供导出功能。

我创建了自己的轻量级框架。它适用于任何Java Bean,您只需要在要导出到CSV,Excel等的字段上添加注释。

链接:https://github.com/abhisoni96/dev-tools

答案 6 :(得分:0)

值得一提的是,车把库https://github.com/jknack/handlebars.java可以简化许多转换任务,包括toCSV。

答案 7 :(得分:0)

您可以使用gererics来上任何课

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());
}