Java tutorial
/* * Copyright (C) 2010 takaji * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ //package dakside.csv; import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.ArrayList; import java.util.Arrays; import java.util.logging.Level; import java.util.logging.Logger; /** * CSV file writer * * @author takaji * */ public final class CSVFileWriter { protected CSVFormat format; protected final BufferedWriter writer; int row = 1; // <editor-fold defaultstate="collapsed" desc="Constructors"> public CSVFileWriter(Writer writer) { this.writer = new BufferedWriter(writer); this.format = new CSVFormat(); } public CSVFileWriter(Writer writer, CSVFormat format) throws FileNotFoundException { this.writer = new BufferedWriter(writer); this.format = format; } public CSVFileWriter(BufferedWriter writer) { this.writer = writer; this.format = new CSVFormat(); } public CSVFileWriter(BufferedWriter writer, CSVFormat format) throws FileNotFoundException { this.writer = writer; this.format = format; } public CSVFileWriter(String filename) { try { this.writer = new BufferedWriter(new FileWriter(new File(filename))); this.format = new CSVFormat(); } catch (IOException ex) { Logger.getLogger(CSVFileWriter.class.getName()).log(Level.SEVERE, null, ex); throw new CSVException(ex); } } public CSVFileWriter(File f) { try { this.writer = new BufferedWriter(new FileWriter(f)); this.format = new CSVFormat(); } catch (IOException ex) { Logger.getLogger(CSVFileWriter.class.getName()).log(Level.SEVERE, null, ex); throw new CSVException(ex); } } public CSVFileWriter(OutputStream input) { writer = new BufferedWriter(new OutputStreamWriter(input)); this.format = new CSVFormat(); } public CSVFileWriter(String filename, CSVFormat format) { try { this.writer = new BufferedWriter(new FileWriter(filename)); this.format = format; } catch (IOException ex) { Logger.getLogger(CSVFileWriter.class.getName()).log(Level.SEVERE, null, ex); throw new CSVException(ex); } } public CSVFileWriter(File f, CSVFormat format) throws IOException { this.writer = new BufferedWriter(new FileWriter(f)); this.format = format; } public CSVFileWriter(OutputStream input, CSVFormat format) { writer = new BufferedWriter(new OutputStreamWriter(input)); this.format = format; } // </editor-fold> /** * Write a line to CSV<br/> * * @throws IOException */ public CSVFileWriter writeLine(CSVLine line) throws CSVException { if (line == null) { return this; } synchronized (this) { // if current line index > 1 // terminate previous line first if (row > 1) { carriageReturn(); } if (!line.isEmpty()) { // try to write each cell in line try { Object[] elements = line.getElements(); for (int i = 0; i < elements.length; i++) { // not first element -> write field delimiter if (i > 0) { writer.append(format.getFieldDelimiter()); } // write cell content Object cell = elements[i]; if (cell != null) { writer.append(escapeString(cell.toString())); } else { writer.append(""); } row++; } } catch (IOException e) { // TODO Auto-generated catch block throw new CSVException(e); } } else { row++; } } return this; } /** * Return carriage * * @throws IOException */ public CSVFileWriter carriageReturn() throws CSVException { try { synchronized (writer) { writer.append(format.getLineTerminator()); } } catch (IOException e) { throw new CSVException("Error while returning carriage.", e); } return this; } /** * Write a file to underline CSV file * * @param file */ public void writeFile(CSVFile file) throws CSVException { if (file == null) { // no need to write return; } CSVLine[] lines = file.getLines(); synchronized (this) { for (int i = 0; i < lines.length; i++) { CSVLine line = lines[i]; writeLine(line); } } } /** * escape a string with text delimiter if needed * * @param str * @return */ private String escapeString(String str) { if (str.indexOf(format.getTextDelimiter()) >= 0 || str.indexOf(format.getLineTerminator()) >= 0 || str.indexOf(format.getFieldDelimiter()) >= 0) { return format.getTextDelimiter() + str.replace("" + format.getTextDelimiter(), "" + format.getTextDelimiter() + format.getTextDelimiter()) + format.getTextDelimiter(); } else { // no need to escape return str; } } /** * close session */ public void close() { try { flush(); } catch (CSVException ex) { //do nothing } try { //auto flush if (writer != null) { writer.close(); } } catch (Exception ex) { Logger.getLogger(CSVFileWriter.class.getName()).log(Level.SEVERE, null, ex); } } /** * Flush buffer to underline stream */ public void flush() { try { synchronized (writer) { writer.flush(); } } catch (Exception ex) { Logger.getLogger(CSVFileWriter.class.getName()).log(Level.SEVERE, null, ex); throw new CSVException("Cannot flush", ex); } } } class CSVFile { private ArrayList<CSVLine> lines; //lines inside a CSV file /** * Default constructor */ public CSVFile() { this.lines = new ArrayList<CSVLine>(); } public CSVLine[] getLines() { return this.lines.toArray(new CSVLine[0]); } /** * Get line at a specified index * @param idx * @return * @throws IndexOutOfBoundsException */ public CSVLine getLine(int idx) throws IndexOutOfBoundsException { return this.lines.get(idx); } /** * Add a new line to current csv * @return new line object */ public CSVLine newLine() { CSVLine line = new CSVLine(); this.lines.add(line); return line; } /** * get number of line * @return number of line */ public int size() { return this.lines.size(); } /** * discard a line at the specified index * @param idx */ public void discard(int idx) { if (idx >= 0 && idx < size()) { this.lines.remove(idx); } } /** * discard empty record */ public void discardEmpty() { for (int i = this.lines.size() - 1; i > -1; i--) { if (this.lines.get(i) == null || this.lines.get(i).isEmpty()) { discard(i); } } } /** * append a CSV line to file (line is ignored if null) * @param line */ void append(CSVLine line) { if (line == null) { return; } this.lines.add(line); } } class CSVException extends RuntimeException { private static final long serialVersionUID = 1L; public CSVException() { } public CSVException(Throwable throwable) { super(throwable); } public CSVException(String message) { super(message); } public CSVException(String message, Throwable throwable) { super(message, throwable); } } class CSVLine { private ArrayList<Object> elements; /** * Default constructor */ public CSVLine() { this.elements = new ArrayList<Object>(); } /** * Get all elements (cells) inside a line * @return empty String array if there's no element found inside */ public Object[] getElements() { return this.elements.toArray(); } /** * Get element at index * @param idx * @return * @throws IndexOutOfBoundsException */ public Object getElementAt(int idx) throws IndexOutOfBoundsException { return elements.get(idx); } /** * Set element at * @param idx * @param value * @throws IndexOutOfBoundsException */ public void setElementAt(int idx, Object value) throws IndexOutOfBoundsException { elements.set(idx, value); } /** * count elements inside this line * @return */ public int size() { return elements.size(); } /** * Add a new element */ public CSVLine add(Object obj) { this.elements.add(obj); return this; } /** * if CSV line is empty * @return */ public boolean isEmpty() { return this.elements.isEmpty(); } /** * Remove all elements */ public void clear() { this.elements.clear(); } /** * Remove element at a specified index * @param idx * @throws IndexOutOfBoundsException */ public void remove(int idx) throws IndexOutOfBoundsException { elements.remove(idx); } /** * Trim down or expand with null cell to a new length * @param newLength */ public void setLength(int newLength) { if (elements.size() > newLength) { //trim down while (elements.size() > newLength) { elements.remove(elements.size() - 1); } } else { //add more while (elements.size() < newLength) { add(null); } } } } class CSVFormat { private String charset; private char fieldDelimiter; private char textDelimiter; private char lineTerminator; private char[] ignoreCharacters; /** * Construct a standard CSV format */ public CSVFormat() { this.setCharset("UTF-8"); this.setFieldDelimiter(','); this.setTextDelimiter('"'); //auto detect line separator String s = System.getProperty("line.separator"); if (s.length() > 0) { this.setLineTerminator(s.charAt(0)); char[] ignoreChars = new char[s.length() - 1]; for (int i = 1; i < s.length(); i++) { ignoreChars[i - 1] = s.charAt(i); } this.setIgnoreCharacters(ignoreChars); } else { this.setLineTerminator('\n'); this.setIgnoreCharacters(new char[] { '\r' }); } } /** * @param lineTerminator * the lineTerminator to set */ public void setLineTerminator(char lineTerminator) { this.lineTerminator = lineTerminator; } /** * @return the lineTerminator */ public char getLineTerminator() { return lineTerminator; } /** * @param ignoreCharacters * the ignoreCharacters to set */ public void setIgnoreCharacters(char[] ignoreCharacters) { this.ignoreCharacters = ignoreCharacters; } /** * @return the ignoreCharacters */ public char[] getIgnoreCharacters() { return ignoreCharacters; } /** * @param charset * the charset to set */ public void setCharset(String charset) { this.charset = charset; } /** * @return the charset */ public String getCharset() { return charset; } /** * @param fieldDelimiter * the fieldDelimiter to set */ public void setFieldDelimiter(char fieldDelimiter) { this.fieldDelimiter = fieldDelimiter; } /** * @return the fieldDelimiter */ public char getFieldDelimiter() { return fieldDelimiter; } /** * @param textDelimiter * the textDelimiter to set */ public void setTextDelimiter(char textDelimiter) { this.textDelimiter = textDelimiter; } /** * @return the textDelimiter */ public char getTextDelimiter() { return textDelimiter; } /** * is ignored characters * @param c * @return */ public boolean isIgnored(char c) { return Arrays.binarySearch(ignoreCharacters, c) >= 0; } }