%metaHeader
   
by Kasper B. Graversen, 2006-2007

%menuBlock %menuBlockCodeExamples

%googleAddsTop %DZoneButton

Code examples

Partial reading and writing

Partial reading and writing of objects is not ordinarily a supported feature in CSV frameworks. This short article will present how elegantly partial reading and partial writing is supported in Super CSV. The core of the problem with especially partial writing is that some columns needs be formatted as plain empty if values are missing, whereas other columns, may need to default to particular strings or numbers such as 0 or -1.

While it has been suggested that Super CSV's write methods should be extended with a default value in case the field to write is null, the current solution presented below is more flexible and elegantly fits into the existing framework. The solution consists of using the concept of cell processors to convert data (or missing data) to whatever values needed.

All the examples here take outset in a simple order class, where an order may be a partial order of another order (if its parentOrder is set to another order).

class Order {
    Integer orderNumber;
    Integer parentOrder;
    Integer productNumber;
    String  userComment;

    public Integer getOrderNumber() {
        return orderNumber;
    }
    public void setOrderNumber(int orderNumber) {
        this.orderNumber = orderNumber;
    }
    public Integer getParentOrder() {
        return parentOrder;
    }
    public void setParentOrder(int parentOrder) {
        this.parentOrder = parentOrder;
    }
    public Integer getProductNumber() {
        return productNumber;
    }
    public void setProductNumber(int productNumber) {
        this.productNumber = productNumber;
    }
    public String getUserComment() {
        return userComment;
    }
    public void setUserComment(String userComment) {
        this.userComment = userComment;
    }
}
The class is used in such a fashion that parentOrder and userComment may only optionally hold values (when appropriate).

Code example: Partially reading objects from a CSV file

This first example shows how to read a partial object from a CSV file utilizing the fact that the CSV file has a header that maps column names to field names of the class.
public void should_partial_read() throws Exception {
    // content of a file containing orders and product numbers
    String fileData = "orderNumber, productNumber\n1,22";

    // setup conversion from String to integers (as our fields are type int)
    CellProcessor[] processing = new CellProcessor[] { new ParseInt(), new ParseInt() };

    // the actual reading
    CsvBeanReader reader = new CsvBeanReader(new StringReader(fileData), CsvPreference.EXCEL_PREFERENCE);
    // get header to identify what fields to populate
    String[] header = reader.getCSVHeader(true);
    Order order = reader.read(PartialReadWriteExamplesTest.Order.class, header, processing);

    // show that only part of the object has been populated with values
    System.out.print("order: " + order.getOrderNumber()
            + " product: " + order.getProductNumber()
            + " parent: " + order.getParentOrder() + "\n**\n");
}
On the screen is printed
order: 1 product: 22 parent: null
**

Code example: Writing partial objects to a CSV file

The following example sets up two order objects and writes them to a file. The key to specifying default values to write in case fields are null is new ConvertNullTo(-1) and new ConvertNullTo("\"\""). The null in the list of processors denotes the columns that need no processing.
public void should_partial_write() throws Exception {
    // The data to write
    Order mainOrder = new Order();
    mainOrder.setOrderNumber(1);
    mainOrder.setProductNumber(42);
    mainOrder.setUserComment("some comment");
    Order subOorder = new Order();
    subOorder.setOrderNumber(2);
    subOorder.setParentOrder(1);
    subOorder.setProductNumber(43);

    // for testing write to a string rather than a file
    StringWriter outFile = new StringWriter();

    // setup header for the file and processors. Notice the match between the header and the attributes of the
    // objects to write. The rules are that
    // - if optional "parent orders" are absent, write -1
    // - and optional user comments absent are written as ""
    String[] header = new String[] { "orderNumber", "parentOrder", "productNumber", "userComment" };
    CellProcessor[] Processing = new CellProcessor[] { null, new ConvertNullTo(-1), null, new ConvertNullTo("\"\"") };

    // write the partial data
    CsvBeanWriter writer = new CsvBeanWriter(outFile, CsvPreference.EXCEL_PREFERENCE);
    writer.writeHeader(header);
    writer.write(mainOrder, header, Processing);
    writer.write(subOorder, header, Processing);
    writer.close();

    // show output
    System.out.println(outFile.toString());
}
On the screen is printed
orderNumber,parentOrder,productNumber,userComment
1,-1,42,some comment
2,1,43,""""""

Conclusion

That's all there is to it. We have showed how to read and write CSV files partially. We have shown the underlying mechanisms for both reading and writing are the same. %googleAddsBottom