Groovy Split CSV

У меня есть файл csv (details.csv), например

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

когда я использую (Примечание: у меня есть другое закрытие выше этого, которое читает все файлы 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() }

Вместо размера 3 я получаю 6 со значениями

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

spilled (",") разделяет данные запятыми (,), но я хочу, чтобы мои результаты были такими

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

Как я могу исправить это закрытие. Пожалуйста помоги! Спасибо


person springpress    schedule 16.08.2012    source источник
comment
String.split (String regex) будет разделен на любое регулярное выражение, которое вы там передаете. Поскольку вы просто переходите, он также разбивает запятые, содержащиеся в значениях. Вам нужно регулярное выражение, которое игнорирует эти запятые, или найдите библиотеку Java / Groovy, которая анализирует файлы CSV.   -  person smcg    schedule 17.08.2012


Ответы (2)


Написать парсер csv - дело непростое.

Я бы позволил кому-то другому делать тяжелую работу и использовать что-нибудь вроде GroovyCsv


Вот как его разобрать с помощью 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
}

Какие отпечатки:

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}

Итак, чтобы получить поле NAME второй строки, вы можете:

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

Какие отпечатки

{abc,def}

Конечно, если CSV - это файл, вы можете:

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

Затем используйте его, как указано выше

person tim_yates    schedule 16.08.2012
comment
Когда я пробую этот api каким-то образом, он объединяет мои заголовки со значениями и не дает в формате, который я ищу. Поскольку мне нужно завершить это как можно скорее, я использовал первый подход в своем ответе ниже. - person springpress; 17.08.2012
comment
@springpress Добавил код, показывающий, как его использовать ... Как видите, он действительно работает ... - person tim_yates; 17.08.2012
comment
Я не уверен, изменилась ли эта логика, но важно отметить, что формат строки csv, определенный в приведенном выше коде, имеет значение. def csv = ''' header1, header2, header3 value1, value2, value3 '' '' не даст ожидаемых результатов. - person dspano; 17.11.2015

Есть два способа сделать. Один использует сбор

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
}

Проблема заключается в том, что между скобками ({}) удаляются запятые, т.е. "{foo, bar}" становится "{foo bar}". Другой способ использования java, и он отлично работает.

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]; 
        }                        
    }    

}

Надеюсь это поможет!

person springpress    schedule 17.08.2012
comment
Вы можете переписать весь этот java-класс в Groovy как public class CSVParser { public String[] parse( String csvLine ) { def matcher = csvLine =~ /"([^"]*)"|(?<=,|^)([^,]*)(?:,|$)/ ; matcher.collect { it[1] } } } - person tim_yates; 17.08.2012
comment
И я бы по-прежнему использовал заранее написанную библиотеку синтаксического анализа CSV - person tim_yates; 17.08.2012
comment
Позвольте мне попробовать это и вернуться к вам. - person springpress; 17.08.2012
comment
Нет, этот класс вообще не работает. Если я напечатаю его [1], его печать будет помещена в каждый столбец csv, кроме чего-то внутри {}, что мне не поможет, извините! Я планирую жить с решением, которое я предоставил в первом - person springpress; 17.08.2012