2012-08-16 9 views
5

Mam pliku csv (details.csv), jakGroovy Podział CSV

ID,NAME,ADDRESS 
1,"{foo,bar}","{123,mainst,ny}" 
2,"{abc,def}","{124,mainst,Va}" 
3,"{pqr,xyz}","{125,mainst,IL}" 

kiedy używam (Uwaga: Mam inne zamknięcie powyżej tego, który czyta wszystkie pliki z katalogu csv)

if(file.getName().equalsIgnoreCase("deatails.csv")) { 
input = new FileInputStream(file) 
reader = new BufferedReader(new InputStreamReader(input)) 
reader.eachLine{line-> def cols = line.split(",") 
println cols.size() } 

Zamiast się rozmiar 3 jestem dostaniem 6 z wartościami

1 
"{foo 
bar}" 
"{123 
mainst 
ny}" 

rozlane („”) jest dzielenie danych przecinkiem (,) ale chcę moje wYNIKI s

1 
"{foo,bar}" 
"{123,mainst,ny}" 

Jak mogę naprawić to zamknięcie. Proszę pomóż! Dzięki

+0

String.split (String regex) zostanie podzielony na dowolne wyrażenie, które będzie tam przekazywane. Ponieważ właśnie przekazujesz ",", dzieli się również na przecinki zawarte w wartościach. Potrzebujesz wyrażeń regularnych, które ignorują te przecinki lub znajdują bibliotekę Java/Groovy, która analizuje pliki CSV. – smcg

Odpowiedz

20

Pisanie parsera CSV jest trudnym zadaniem.

chciałbym niech ktoś inny zrobi ciężką pracę i użyć coś like GroovyCsv


Oto jak do analizowania go GroovyCsv

// I'm using Grab instead of just adding the jar and its 
// dependencies to the classpath 
@Grab('com.xlson.groovycsv:groovycsv:1.0') 
import com.xlson.groovycsv.CsvParser 

def csv = '''ID,NAME,ADDRESS 
1,"{foo,bar}","{123,mainst,ny}" 
2,"{abc,def}","{124,mainst,Va}" 
3,"{pqr,xyz}","{125,mainst,IL}"''' 

def csva = CsvParser.parseCsv(csv) 
csva.each { 
    println it 
} 

która drukuje:

ID: 1, NAME: {foo,bar}, ADDRESS: {123,mainst,ny} 
ID: 2, NAME: {abc,def}, ADDRESS: {124,mainst,Va} 
ID: 3, NAME: {pqr,xyz}, ADDRESS: {125,mainst,IL} 

Tak więc, aby uzyskać pole NAZWA drugiego rzędu, można wykonać:

def csvb = CsvParser.parseCsv(csv) 
println csvb[ 1 ].NAME 

która drukuje

{abc,def} 

Oczywiście, jeśli CSV jest plik, można zrobić:

def csvc = new File('path/to/csv').withReader { 
    CsvParser.parseCsv(it) 
} 

następnie używać go jak wyżej

+0

Nie, ten api mi nie pomógł! – springpress

+1

@springpress Dlaczego nie? Jakieś wyjaśnienie? –

+0

Kiedy próbuję tego api jak połączyć moje nagłówki z wartościami, a nie podając w formacie, którego szukam. Ponieważ muszę wykonać to ASAP, podążałem za pierwszym podejściem w mojej odpowiedzi poniżej. – springpress

0

Istnieją dwa sposoby robić. Jeden używa zbierać

def processCsvData(Map csvDataMap, File file) 
{ 

    InputStream inputFile = new FileInputStream(file); 
    String[] lines = inputFile.text.split('\n') 
    List<String[]> rows = lines.collect {it.split(',')} 
      // Add processing logic 
} 

Tutaj problemem jest to, że usuwa przecinków między klamrowych ({}), czyli "{foo, bar}" staje się "{foo bar}" Innym sposobem przy użyciu języka Java, a to działa dobrze

public class CSVParser { 

    /* 
    * This Pattern will match on either quoted text or text between commas, including 
    * whitespace, and accounting for beginning and end of line. 
    */ 
    private final Pattern csvPattern = Pattern.compile("\"([^\"]*)\"|(?<=,|^)([^,]*)(?:,|$)"); 
    private ArrayList<String> allMatches = null;   
    private Matcher matcher = null; 
    private int size; 

    public CSVParser() {     
     allMatches = new ArrayList<String>(); 
     matcher = null; 
    } 

    public String[] parse(String csvLine) { 
     matcher = csvPattern.matcher(csvLine); 
     allMatches.clear(); 
     String match; 
     while (matcher.find()) { 
       match = matcher.group(1); 
       if (match!=null) { 
         allMatches.add(match); 
       } 
       else { 
         allMatches.add(matcher.group(2)); 
       } 
     } 

     size = allMatches.size();     
     if (size > 0) { 
       return allMatches.toArray(new String[size]); 
     } 
     else { 
       return new String[0]; 
     }       
    }  

} 

Mam nadzieję, że to pomoże!

+0

Możesz przepisać całą klasę java w Groovy jako "public class CSVParser {public String [] parsowanie (String csvLine) {def matcher = csvLine = ~ /" ([^ "] *)" | (? <=, | ^) ([^,] *) (?:, | $) /; matcher.collect {it [1]}}} ' –

+0

I nadal używałbym wstępnie napisanej biblioteki parsowania CSV –

+0

Pozwól mi spróbować i wrócić – springpress