Open Source Repository

Home /csv/supercsv-1.52 | Repository Home


org/supercsv/io/AbstractCsvWriter.java
package org.supercsv.io;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.List;

import org.supercsv.exception.NullInputException;
import org.supercsv.exception.SuperCSVException;
import org.supercsv.prefs.CsvPreference;
import org.supercsv.util.CSVContext;

/**
 * The writer class capable of writing arrays, maps,... to a CSV file. Notice that the cell processors can also be
 * utilized when writing. E.g. they can help ensure that only numbers are written in numeric columns, that numbers are
 * unique or the output does not contain certain characters or exceed specified string lengths.
 
 @author Kasper B. Graversen
 */
public abstract class AbstractCsvWriter implements ICsvWriter {
final StringBuilder sb = new StringBuilder();
BufferedWriter outStream;
int lineNo;
CsvPreference preference;

protected AbstractCsvWriter(final Writer stream, final CsvPreference preference) {
  setPreferences(preference);
  outStream = new BufferedWriter(stream);
  lineNo = 1;
}

/**
 * {@inheritDoc}
 */
public void close() throws IOException {
  outStream.flush();
  outStream.close();
}

/**
 * Make a string ready for writing by escaping various characters as specified by the CSV format
 
 @param csvElem
 *            an elem of a csv file
 @return an escaped version of the csv elem ready for persisting
 */
protected String escapeString(final String csvElem) {
  ifcsvElem.length() == ) {
    return "";
  }
  
  sb.delete(0, sb.length())// reusing builder object
  
  final int delimiter = preference.getDelimiterChar();
  final char quote = (charpreference.getQuoteChar();
  final char whiteSpace = ' ';
  final String EOLSymbols = preference.getEndOfLineSymbols();
  
  boolean needForEscape = false// if newline or start with space
  ifcsvElem.charAt(0== whiteSpace ) {
    needForEscape = true;
  }
  
  char c;
  final int lastPos = csvElem.length() 1;
  forint i = 0; i <= lastPos; i++ ) {
    
    c = csvElem.charAt(i);
    
    ifc == delimiter ) {
      needForEscape = true;
      sb.append(c);
    }
    else
      ifc == quote ) {
        // if its the first character, escape it and set need for space
        ifi == ) {
          sb.append(quote);
          sb.append(quote);
          needForEscape = true;
        }
        else {
          sb.append(quote);
          sb.append(quote);
          needForEscape = true// TODO review comments above
        }
      }
      else
        ifc == '\n' ) {
          needForEscape = true;
          sb.append(EOLSymbols);
        }
        else {
          sb.append(c);
        }
  }
  
  // if element contains a newline (mac,windows or linux), escape the
  // whole with a surrounding quotes
  ifneedForEscape ) {
    return quote + sb.toString() + quote;
  }
  
  return sb.toString();
  
}

/**
 * {@inheritDoc}
 */
public int getLineNumber() {
  return lineNo;
}

/**
 * {@inheritDoc}
 */
public ICsvWriter setPreferences(final CsvPreference preference) {
  this.preference = preference;
  return this;
}

/**
 * The actual write to stream
 */
protected void write(final List<? extends Object> contentthrows IOException {
  write(content.toArray());
}

protected void write(final Object... contentthrows IOException {
  // convert object array to strings and write them
  final String[] strarr = new String[content.length];
  int i = 0;
  forfinal Object o : content ) {
    ifo == null ) {
      throw new NullInputException("Object at position " + i + " is null"new CSVContext(getLineNumber(), i),
        (Throwablenull);
    }
    strarr[i++= o.toString();
  }
  write(strarr);
}

protected void write(final String... contentthrows IOException {
  lineNo++;
  
  final int delimiter = preference.getDelimiterChar();
  int i = 0;
  switchcontent.length ) {
  case 0:
    throw new SuperCSVException("There is no content to write for line " + getLineNumber()new CSVContext(
      getLineNumber()0));
    
  case 1// just write last element after switch
    break;
  
  default:
    // write first 0..N-1 elems
    for; i < content.length - 1; i++ ) {
      outStream.write(escapeString(content[i]));
      outStream.write(delimiter);
    }
    break;
  }
  
  // write last elem (without delimiter) and the EOL
  outStream.write(escapeString(content[i]));
  outStream.write(preference.getEndOfLineSymbols());
  return;
}

/**
 * {@inheritDoc}
 */
public void writeHeader(final String... headerthrows IOException, SuperCSVException {
  this.write(header);
}

}