Giulio Pulina
Giulio Pulina

Reputation: 404

Spring Batch FlatFileItemWriter - output customization

I would have the need to produce a CSV File with the following requirements:

Input:

Expected output:

"Field1"|"Field2With\\Backslash\"DoubleQuotes\"And|Pipe"|"Field3"

Is it possible to obtain such an output?

Upvotes: 0

Views: 935

Answers (2)

Giulio Pulina
Giulio Pulina

Reputation: 404

The best solution is to implement quoting and escaping in a subclass of ExtractorLineAggregator.

public final class CustomDelimitedLineAggregator<T> extends ExtractorLineAggregator<T> {
     private String delimiterChar = ",";
     private String quoteChar = "\"";
     private String escapeChar = "\\";

     public CustomDelimitedLineAggregator() {
     }

     public CustomDelimitedLineAggregator(String delimiterChar){
         this.delimiterChar = delimiterChar;
     }

     // getters and setters..

     @Override
     public String doAggregate(Object[] fieldList) {
         if (isEmpty(fieldList)) {
             return quote("");
         }

         if (fieldList.length == 1) {
             return quote(escape((valueOf(fieldList[0]))));
         }

         String aggregated = "";
         for (int i = 0; i < fieldList.length; i++) {
             if (i > 0) {
                 aggregated += delimiterChar;
             }
             String field = valueOf(fieldList[i]);
             aggregated+=(quote(escape(field)));
          }
         
          return aggregated;
    }

    public String doAggregate(List<String> fieldList) {
        if (isEmpty(fieldList)) {
             return doAggregate((Object[]) null);
        }
        return doAggregate(fieldList.toArray(new Object[0]));
    }

    private String escape(String s) {
        if (s == null) {
            return null;
        }
        return s.replace(escapeChar, escapeChar + escapeChar)
            .replace(quoteChar, escapeChar + quoteChar);
    }

    private String quote(String s) {
        if (s == null) {
            return quoteChar + quoteChar;
        }
        return quoteChar + s + quoteChar;
    }
}

Upvotes: 0

ACH
ACH

Reputation: 195

Basically, you just want to process your fields before writing it. You could do it with these 2 ways

Let's say this method processes your field

public String escape(String str) {
    str = "\"" + str + "\"";
    str = str.replace("|", "\\|");
    str = str.replace("\\", "\\\\");
    return str;
}

1 - Process it during processor - preferred

@Override
public A process(B b) throws Exception {
    A a = new A();
    //Process b to a...    

    a.setField1(escape(a.getField1)); //For each fields
    return a;
}

2 - Process it before writing in custom Writer

public class EscapeFlatFileItemWriter<A> extends FlatFileItemWriter<A> {

    @Override
    public void write(List<? extends A> items) throws Exception {
        for (A a : items) {
            a.setField1(escape(a.getField1)); //For each fields
        }
        super.write(items);
    }
}

Upvotes: 0

Related Questions