// Catalano IO Library
// The Catalano Framework
//
// Copyright © Diego Catalano, 2012-2016
// diego.catalano at live.com
//
//
//    This library is free software; you can redistribute it and/or
//    modify it under the terms of the GNU Lesser General Public
//    License as published by the Free Software Foundation; either
//    version 2.1 of the License, or (at your option) any later version.
//
//    This library 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
//    Lesser General Public License for more details.
//
//    You should have received a copy of the GNU Lesser General Public
//    License along with this library; if not, write to the Free Software
//    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
//

package Catalano.IO;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * CSV Parser, handle csv files.
 * @author Diego Catalano
 */
public class CSVParser {
    
    private char delimiter = ',';
    private int startRow = 0;
    private int startCol = 0;
    private int endCol = -1;
    
    String charset = "UTF-8";
    String newLine = System.getProperty("line.separator");

    /**
     * Get the delimiter.
     * @return Delimiter.
     */
    public char getDelimiter() {
        return delimiter;
    }

    /**
     * Set the delimiter.
     * @param delimiter Delimiter.
     */
    public void setDelimiter(char delimiter) {
        this.delimiter = delimiter;
    }

    /**
     * Get new line separator.
     * @return New line separator.
     */
    public String getNewLine() {
        return newLine;
    }

    /**
     * Set new line separator.
     * @param newLine New line separator.
     */
    public void setNewLine(String newLine) {
        this.newLine = newLine;
    }

    /**
     * Get start row index.
     * @return Start row index.
     */
    public int getStartRow() {
        return startRow;
    }

    /**
     * Set start row index.
     * @param startRow Start row index.
     */
    public void setStartRow(int startRow) {
        this.startRow = startRow;
    }

    /**
     * Get start column index.
     * @return Start column index.
     */
    public int getStartColumn() {
        return startCol;
    }

    /**
     * Set start column index.
     * @param startCol Start column index.
     */
    public void setStartColumn(int startCol) {
        this.startCol = startCol;
    }

    /**
     * Get end column index.
     * Default: -1, It means to get all columns.
     * @return 
     */
    public int getEndColumn() {
        return endCol;
    }

    /**
     * Set end column index.
     * Value: -1 for to set the last column.
     * @param endCol End column index.
     */
    public void setEndColumn(int endCol) {
        this.endCol = endCol;
    }

    /**
     * Initialize a new instance of the CSVParser class.
     */
    public CSVParser() {}
    
    /**
     * Initialize a new instance of the CSVParser class.
     * @param delimiter Delimiter.
     */
    public CSVParser(char delimiter) {
        this.delimiter = delimiter;
    }
    
    /**
     * Initialize a new instance of the CSVParser class.
     * @param delimiter Delimiter.
     * @param startRow Start row.
     */
    public CSVParser(char delimiter, int startRow){
        this.delimiter = delimiter;
        this.startRow = startRow;
    }
    
    /**
     * Initialize a new instance of the CSVParser class.
     * @param delimiter Delimiter.
     * @param startRow Start row.
     * @param startColumn Start column.
     */
    public CSVParser(char delimiter, int startRow, int startColumn){
        this.delimiter = delimiter;
        this.startRow = startRow;
        this.startCol = startColumn;
    }
    
    /**
     * Initialize a new instance of the CSVParser class.
     * @param delimiter Delimiter.
     * @param startRow Start row.
     * @param startColumn Start column.
     * @param endColumn End column.
     */
    public CSVParser(char delimiter, int startRow, int startColumn, int endColumn){
        this.delimiter = delimiter;
        this.startRow = startRow;
        this.startCol = startColumn;
        this.endCol = endColumn;
    }
    
    /**
     * Read CSV and convert to object type.
     * The method find the constructor that contains the maximum parameters.
     * @param  Object type.
     * @param filename CSV filename.
     * @param clazz Object type.
     * @return List of user definied type.
     */
    public  List Read(String filename, Class clazz){
        String[][] data = Read(filename);
        return toObject(data, clazz);
    }
    
    /**
     * Read CSV.
     * @param filename Filename.
     * @return CSV table of string.
     */
    public String[][] Read(String filename){
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filename), charset));
            
            String line;
            List lines = new ArrayList();
            while ((line = br.readLine()) != null) {
                lines.add(line);
            }
            
            //Check the limits
            if(endCol == -1)
                endCol = lines.get(startRow).split(String.valueOf(delimiter)).length;
            
            
            if(lines.size() > 0) {
                String[] temp = lines.get(startRow).split(String.valueOf(delimiter));
                String[][] data = new String[lines.size() - startRow][temp.length - startCol];
                int idxI = 0;
                for (int i = startRow; i < lines.size(); i++) {
                    int idxJ = 0;
                    temp = lines.get(i).split(String.valueOf(delimiter));
                    for (int j = startCol; j < endCol; j++) {
                        data[idxI][idxJ] = temp[j];
                        idxJ++;
                    }
                    idxI++;
                }

                return data;
            }
            
        } catch (FileNotFoundException ex) {
            Logger.getLogger(CSVParser.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(CSVParser.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        return null;
    }
    
    public double[][] ReadAsDouble(String filename){
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filename), charset));
            
            String line;
            List lines = new ArrayList();
            while ((line = br.readLine()) != null) {
                lines.add(line);
            }
            
            //Check the limits
            if(endCol == -1)
                endCol = lines.get(startRow).split(String.valueOf(delimiter)).length;
            
            if(lines.size() > 0) {
                String[] temp = lines.get(startRow).split(String.valueOf(delimiter));
                double[][] data = new double[lines.size() - startRow][temp.length - startCol];
                int idxI = 0;
                for (int i = startRow; i < lines.size(); i++) {
                    int idxJ = 0;
                    temp = lines.get(i).split(String.valueOf(delimiter));
                    for (int j = startCol; j < endCol; j++) {
                        String t = fix(temp[j]);
                        data[idxI][idxJ] = t.equals("") ? Double.NaN : Double.valueOf(t);
                        idxJ++;
                    }
                    idxI++;
                }
                
                return data;
            }
            
        } catch (FileNotFoundException ex) {
            Logger.getLogger(CSVParser.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(CSVParser.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        return null;
    }
    
    public int[][] ReadAsInt(String filename){
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filename), charset));
            
            String line;
            List lines = new ArrayList();
            while ((line = br.readLine()) != null) {
                lines.add(line);
            }
            
            //Check the limits
            if(endCol == -1)
                endCol = lines.get(startRow).split(String.valueOf(delimiter)).length;
            
            if(lines.size() > 0) {
                String[] temp = lines.get(startRow).split(String.valueOf(delimiter));
                int[][] data = new int[lines.size() - startRow][temp.length - startCol];
                int idxI = 0;
                for (int i = startRow; i < lines.size(); i++) {
                    int idxJ = 0;
                    temp = lines.get(i).split(String.valueOf(delimiter));
                    for (int j = startCol; j < endCol; j++) {
                        data[idxI][idxJ] = Integer.valueOf(fix(temp[j]));
                        idxJ++;
                    }
                    idxI++;
                }

                return data;
            }
            
        } catch (FileNotFoundException ex) {
            Logger.getLogger(CSVParser.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(CSVParser.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        return null;
    }
    
    /**
     * Fix invalid chars.
     * @param x String
     * @return String.
     */
    private static String fix(String x){
        String r = "";
        for (int i = 0; i < x.length(); i++) {
            char c = x.charAt(i);
            if(Character.isDigit(c) || c == '.' || c == '-' || c == 'E')
                r += c;
        }
        return r;
    }
    
    /**
     * Convert the CSV string to user definied type.
     * The method find the constructor that contains the maximum parameters.
     * @param  Object type.
     * @param data CSV data.
     * @param cls Object type.
     * @return List of user definied type.
     */
    private  List toObject(String[][] data, Class cls){
        
        int p = 0;
        Class[] paramTypes = null;
        
        for (Constructor con : cls.getConstructors()) {
            if(con.getParameterCount() > p){
                p = con.getParameterCount();
                paramTypes = con.getParameterTypes();
            }
        }
        
        List lst = new ArrayList(data.length);
       
        try{
            for (int i = 0; i < data.length - startRow; i++) {
                Constructor c = cls.getConstructor(paramTypes);
                Object[] obj = new Object[paramTypes.length];
                for (int j = 0; j < paramTypes.length; j++) {
                    if(paramTypes[j] == int.class){
                        obj[j] = Integer.parseInt(data[i][j]);
                    }
                    else if(paramTypes[j] == boolean.class){
                        obj[j] = Boolean.parseBoolean(data[i][j]);
                    }
                    else if(paramTypes[j] == double.class){
                        obj[j] = Double.parseDouble(data[i][j]);
                    }
                    else if(paramTypes[j] == float.class){
                        obj[j] = Float.parseFloat(data[i][j]);
                    }
                    else if(paramTypes[j] == String.class){
                        obj[j] = data[i][j];
                    }
                }
                
                lst.add((T) c.newInstance(obj));
            }
            return lst;
        }
        catch (NoSuchMethodException ex) {
            Logger.getLogger(CSVParser.class.getName()).log(Level.SEVERE, null, ex);
        }
        catch (SecurityException ex) {
            Logger.getLogger(CSVParser.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            Logger.getLogger(CSVParser.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(CSVParser.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalArgumentException ex) {
            Logger.getLogger(CSVParser.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvocationTargetException ex) {
            Logger.getLogger(CSVParser.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }
    
    /**
     * Write the matrix of string in csv file format.
     * @param data Data.
     * @param filename Filename.
     */
    public void Write(String[][] data, String filename){
        try {
            FileWriter fw = new FileWriter(filename);
            
            boolean isLastCol;
            for (int i = 0; i < data.length; i++) {
                isLastCol = false;
                for (int j = 0; j < data[0].length; j++) {
                    if(j==data[0].length-1) isLastCol = true;
                    if(isLastCol)
                        fw.append(data[i][j]);
                    else
                        fw.append(data[i][j] + delimiter);
                }
                fw.append(newLine);
            }
            
            fw.flush();
            fw.close();
            
        } catch (IOException ex) {
            Logger.getLogger(CSVParser.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    /**
     * Write the matrix of integer in csv file format.
     * @param data Data.
     * @param filename Filename.
     */
    public void Write(int[][] data, String filename){
        try {
            FileWriter fw = new FileWriter(filename);
            
            boolean isLastCol;
            for (int i = 0; i < data.length; i++) {
                isLastCol = false;
                for (int j = 0; j < data[0].length; j++) {
                    if(j==data[0].length-1) isLastCol = true;
                    if(isLastCol)
                        fw.append(String.valueOf(data[i][j]));
                    else
                        fw.append(String.valueOf(data[i][j]) + delimiter);
                }
                fw.append(newLine);
            }
            
            fw.flush();
            fw.close();
            
        } catch (IOException ex) {
            Logger.getLogger(CSVParser.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    public void Write(double[][] data, String filename){
        Write(data, filename, -1);
    }
    
    /**
     * Write the matrix of integer in csv file format.
     * @param data Data.
     * @param filename Filename.
     */
    public void Write(double[][] data, String filename, int decimalPlaces){
        try {
            
            String dec = "%." + decimalPlaces + "f";
            
            FileWriter fw = new FileWriter(filename);
            
            boolean isLastCol;
            for (int i = 0; i < data.length; i++) {
                isLastCol = false;
                for (int j = 0; j < data[0].length; j++) {
                    if(j==data[0].length-1) isLastCol = true;
                    if(decimalPlaces >= 0){
                        if(isLastCol)
                            fw.append(String.format(Locale.US, dec, data[i][j]));
                        else
                            fw.append(String.format(Locale.US, dec, data[i][j]) + delimiter);
                    }
                    else{
                        if(isLastCol)
                            fw.append(String.valueOf(data[i][j]));
                        else
                            fw.append(String.valueOf(data[i][j]) + delimiter);
                    }
                }
                fw.append(newLine);
            }
            
            fw.flush();
            fw.close();
            
        } catch (IOException ex) {
            Logger.getLogger(CSVParser.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
 

Ads help maintain this website.