Search code examples
javaspring-batch

Spring Batch FlatFileItemWriter - output customization


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

  • Every field is surrounded by double quotes
  • Double quotes are escaped with backslash
  • Backslash is escaped with backslash

Input:

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

Expected output:

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

Is it possible to obtain such an output?


Solution

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