package com.akjava.lib.common.csv;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.google.common.base.Preconditions;
import com.google.common.io.LineProcessor;
public class CSVProcessor implements LineProcessor<List<List<String>>> {
boolean inQuote=false;
boolean inText=false;
private char separator;
private char quotechar;
public CSVProcessor(){
this('\t','"');
}
public CSVProcessor(char separator, char quotechar){
Preconditions.checkArgument(separator!=quotechar);
Preconditions.checkArgument(separator!='\r');
Preconditions.checkArgument(separator!='\n');
Preconditions.checkArgument(quotechar!='\r');
Preconditions.checkArgument(quotechar!='\n');
this.separator=separator;
this.quotechar=quotechar;
}
public CSVProcessor(char separator) {
this(separator,'"');
}
public void reset(){
inQuote=false;
inText=false;
resultCalled=false;
values="";
columns=new ArrayList<String>();
result=new ArrayList<List<String>>();
}
private boolean resultCalled;
List<List<String>> result=new ArrayList<List<String>>();
List<String> columns=new ArrayList<String>();
String values="";
@Override
public List<List<String>> getResult() {
if(!resultCalled){
if(!values.isEmpty()){
//LogUtils.log("values not empty add:"+values);
columns.add(values);
}
if(!columns.isEmpty()){
//LogUtils.log("columns not empty add:"+columns);
result.add(columns);
}
resultCalled=true;
}
return result;
}
@Override
public boolean processLine(String line) throws IOException {
if(resultCalled){
throw new IOException("need reset()");
}
if(line.isEmpty()){
columns.add(values);
values="";
result.add(columns);
columns=new ArrayList<String>();
return true;
}
for(int i=0;i<line.length();i++){
char ch=line.charAt(i);
if(ch==quotechar){
if(inQuote){
//check escaped
if(i+1<line.length()){
char next=line.charAt(i+1);
if(next==quotechar){//escaped
values+=ch;
//values+=next;
++i;//skip
//System.out.println("inQuote but next is not quote");
continue;
}else{
//System.out.println("inQuote but next is not quote:"+next);
}
}
//System.out.println("set inQuote=false");
inQuote=false;
}else{
//skip
if(inText){
values+=ch;
}else{
// System.out.println("set inQuote=true");
inQuote=true;
}
}
}else if(ch==separator){
if(inQuote){//inQuote separator ignored
values+=ch;
}else{
//value break
columns.add(values);
values="";
inText=false;
}
}else{
values+=ch;
if(!inQuote){
inText=true;//this csv parser can contain quote
}
}
}
//do something end of line
if(inQuote){//inQuote line separator ignored
values+="\n";//add line separator,but this is somekind bug,not added original line separator.
}else{
//end line is usually end of row,refresh it
columns.add(values);
values="";
result.add(columns);
columns=new ArrayList<String>();
inText=false;
}
return true;
}
}