【问题标题】:Selective Serialization to CSV, Java选择性序列化为 CSV、Java
【发布时间】:2014-12-20 04:35:40
【问题描述】:

我正在使用 jsefa 库来选择性地反序列化 csv,例如。仅映射标头编号。 1,3,5 到我的对象,这很好用。

现在我想做相反的事情,选择性地将我的对象序列化到标题位置 1、3、5,并且休息位置应该自动用分号 (;) 分隔。 所以输出看起来像这样:

Header1;Header2;Header3;Header4;Header5;Header6;Header7
bla1;;bla3;;bla5

任何人都可以建议,如何使用 jsefa 或任何其他库来完成。

【问题讨论】:

  • 目前还不清楚您尝试了什么以及如何尝试。以及你是如何尝试 opencsv 和 supercsv 的。
  • @RobAu 嗨,我没有尝试过 opencsv 或 supercsv,我添加了这些标签,所以使用过这些库的人可以提供一些建议。我只试过jsefa。让我试着说得更清楚。

标签: java csv opencsv supercsv


【解决方案1】:

这当然可以通过 Super CSV 实现。只需在 nameMapping 数组中提供一个 null 条目即可始终写入一个空白列。

private static void writePartial() throws IOException {
    Person person1 = new Person("John", "K", "Smith");
    Person person2 = new Person("Sally", "T", "Brown");

    CsvPreference csvPrefs = new CsvPreference.Builder('"', ';', "\n").build();
    String[] nameMapping = new String[] { "firstName", null, "lastName" };

    try (ICsvBeanWriter writer = new CsvBeanWriter(new FileWriter("output.csv"), csvPrefs)) {
        writer.writeHeader("firstName", "middleName", "lastName");
        for( Person p : Arrays.asList(person1, person2) ) {
            writer.write(p, nameMapping);
        }
    }
}

你应该得到以下输出:

firstName;middleName;lastName
John;;Smith
Sally;;Brown

这可能是最简单的解决方案,但如果您需要更灵活的方法(例如,您可能想要验证字段值,但永远不要编写它),那么您可以创建一个自定义单元处理器以确保该字段永远不会书面。 只需定义一个始终忽略 bean 中的值的单元处理器:

public class Ignore extends CellProcessorAdaptor {

    @Override
    public Object execute(Object value, CsvContext context) {
        return null;
    }

}

然后使用它:

private static void writePartial() throws IOException {
    Person person1 = new Person("John", "K", "Smith");
    Person person2 = new Person("Sally", "T", "Brown");

    CsvPreference csvPrefs = new CsvPreference.Builder('"', ';', "\n").build();
    String[] nameMapping = new String[] { "firstName", "middleName", "lastName" };
    CellProcessor[] processors = new CellProcessor[] { new Optional(), new Ignore(), new Optional() };

    try (ICsvBeanWriter writer = new CsvBeanWriter(new FileWriter("output.csv"), csvPrefs)) {
        writer.writeHeader(nameMapping);
        for( Person p : Arrays.asList(person1, person2) ) {
            writer.write(p, nameMapping, processors);
        }
    }
}

因此,您可以将其链接在一起 new NotNull(new Ignore()) 以验证 bean 的 middleName 字段始终具有值,但永远不要写入它。这也意味着如果您稍后改变主意并想要写入该值,您可以将 Ignore() 处理器替换为 Optional()(或 NotNull(),或任何您喜欢的),然后查看它应该写中间名字段,而不是忽略它。

【讨论】:

  • 这当然可以,但是如何使用 jsefa 来实现呢?
【解决方案2】:

只需使用 uniVocity-parsers,因为它比任何其他用于 Java 的 CSV 解析库更简单、更快:

阅读:

CsvParserSettings settings = new CsvParserSettings();
settings.selectIndexes(1, 3, 5);

CsvParser parser = new CsvParser(settings);
List<String[]> parsedRows = parser.parseAll(yourJavaIoReader);

写作:

CsvWriterSettings settings = new CsvWriterSettings();
settings.selectIndexes(1, 3, 5);

CsvWriter writer = new CsvWriter(outputWriter, settings);
writer.writeAllRowsAndClose(buildMyListOfRowsWith3Elements());

披露:我是这个库的作者。它是开源免费的(Apache V2.0 许可)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-02
    • 1970-01-01
    • 2015-02-13
    • 2011-02-03
    • 2010-12-21
    • 1970-01-01
    • 2017-11-04
    • 1970-01-01
    相关资源
    最近更新 更多