package com.akjava.lib.common.utils;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.akjava.lib.common.functions.SplitLineFunction;
import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Lists;
public class CSVUtils {
private static final Splitter NLinerSplitter=Splitter.on('\n');
private CSVUtils(){}
public static String toNLineSeparator(String text){
String ret=text.replace("\r\n", "\n");
ret= ret.replace("\r", "\n");
return ret;
}
public static List<String> splitLinesWithGuava(String text){
return splitLinesWithGuava(text,false);
}
public static List<String> splitLinesWithGuava(String text,boolean removeEmptyLine){
if(text.isEmpty()){
//return Lists.newArrayList();//return empty;
}
text=toNLineSeparator(text);
if(removeEmptyLine){
return removeEmptyLine(NLinerSplitter.split(text));
}else{
return Lists.newArrayList(NLinerSplitter.split(text));
}
}
/**
* this is simple but emit last continue lineseparator ,if it's problem use splitLinesWithGuava
* @param text
* @return
*/
public static String[] splitLines(String text){
text=toNLineSeparator(text);
String[] lines=text.split("\n");
return lines;
}
public static String[] splitAtFirst(String text,String separator){
int index=text.indexOf(separator);
if(index==-1){
return new String[]{text};
}else{
return new String[]{text.substring(0, index),text.substring(index+separator.length())};
}
}
public static String[][] csvTextToArray(String line,char separator){
line=toNLineSeparator(line);
String[] lines=line.split("\n");
String ret[][]=new String[lines.length][0];
for (int i = 0; i < lines.length; i++) {
String csv[]=lines[i].split(""+separator);
ret[i]=new String[csv.length];
for (int j = 0; j < csv.length; j++) {
ret[i][j]=csv[j];
}
}
return ret;
}
public static int countMaxColumnSizeByList(List<List<String>> csvs){
int max=0;
for(List<String> csv:csvs){
if(csv.size()>max){
max=csv.size();
}
}
return max;
}
public static int countMaxColumnSizeByArray(List<String[]> csvs){
int max=0;
for(String[] csv:csvs){
if(csv.length>max){
max=csv.length;
}
}
return max;
}
/**
* support multiple csv separator
* @param text
* @param tabbedCsv
* @param conmaCsv
* @return
*/
public static List<List<String>> csvToListList(String text,boolean tabbedCsv,boolean conmaCsv){
if(text.isEmpty()){
return new ArrayList<List<String>>();
}
List<String> lines=CSVUtils.splitLinesWithGuava(text);
return Lists.transform(Lists.newArrayList(lines), new SplitLineFunction(tabbedCsv,conmaCsv));
}
public static List<String[]> csvTextToArrayList(String text,char separator){
text=toNLineSeparator(text);
String[] lines=text.split("\n");
List<String[]> ret=new ArrayList<String[]>();
for (int i = 0; i < lines.length; i++) {
String csv[]=lines[i].split(""+separator);
ret.add(csv);
}
return ret;
}
public static String joinOn(Iterable<String> values,String separator){
StringBuilder builder=new StringBuilder();
Iterator<String> itor=values.iterator();
while(itor.hasNext()){
builder.append(itor.next());
if(itor.hasNext()){
builder.append(separator);
}
}
return builder.toString();
}
/**
*
* csv value cracch quot if it contain a line-separator.
* and that case quot string must be escaped with additional quot;
*
* can't read this csv from CSVReader
*
* @param text
* @param splitString
* @param replaceSplitChar usually use empty to remove splitString
* @return
*/
public static String toCsvString(String text,String splitString,String replaceSplitChar){
boolean containLineSeparator=text.indexOf("\n")!=-1;
if(!containLineSeparator){
containLineSeparator=text.indexOf("\r")!=-1;
}
text=text.replace(splitString, replaceSplitChar);
if(containLineSeparator){
text=text.replace("\"", "\"\"");
return "\""+text+"\"";
}else{//
return text;
}
}
/*
* this works fine on CSVReader
*/
public static String toSimpleQuoteString(String text){
text=text.replace("\"", "\"\"");
return "\""+text+"\"";
}
public static String mapToCsv(Map<String,String> map,List<String> keys,String splitString){
List<String> result=new ArrayList<String>();
for(String key:keys){
if(map.get(key)!=null){
result.add(toCsvString(map.get(key),splitString,""));
}else{
result.add("");
}
}
return Joiner.on(splitString).join(result);
}
public static String[][] csvToArray(String line){
return csvTextToArray(line,',');
}
public static Map<String,String> csvTextToMap(char separator,String text){
Map<String,String> map=new LinkedHashMap<String,String>();
String[] lines=splitLines(text);
for(String line:lines){
if(line.isEmpty()){
continue;
}
int sp=line.indexOf(separator);
if(sp!=-1){
map.put(line.substring(0,sp),line.substring(sp+1));
}else{
map.put(line, "");
}
}
return map;
}
public static List<String> removeEmptyLine(Iterable<String> lines){
return Lists.newArrayList(FluentIterable.from(lines).filter(new Predicate<String>(){
@Override
public boolean apply(String input) {
return !Strings.isNullOrEmpty(input);
}}));
}
/**
* need \r\n to \n
* @param line
* @return
*/
public static String removeEmptyLine(String line){
line=toNLineSeparator(line);
String[] lines=line.split("\n");
String ret="";
for (int i = 0; i < lines.length; i++) {
if(!lines[i].equals("")){
ret+=lines[i];
if(i!=lines.length-1){
ret+="\n";
}else{
ret+="\n";
}
}
}
return ret;
}
}