【问题标题】:Groovy Split CSVGroovy 拆分 CSV
【发布时间】:2012-08-13 06:36:00
【问题描述】:

我有一个类似的 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}"

spilt(",") 用逗号(,) 分割数据,但我希望我的结果为

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

如何解决此关闭问题。请帮忙!谢谢

【问题讨论】:

  • String.split(String regex) 将根据您传入的任何正则表达式进行拆分。由于您只是传入“,”,因此它也会拆分值中包含的逗号。您需要一个忽略这些逗号的正则表达式,或者找到一个解析 CSV 文件的 Java/Groovy 库。

标签: csv groovy split


【解决方案1】:

编写 csv 解析器是一项棘手的工作。

我会让其他人做艰苦的工作,并使用一些like 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 )
}

然后如上使用

【讨论】:

  • 当我尝试这个 api 时,它是如何将我的标题与值结合起来的,而不是以我正在寻找的格式给出的。因为我需要尽快完成,所以我在下面的回答中采用了第一种方法。
  • @springpress 添加了一些代码来展示如何使用它...如您所见,它确实工作...
  • 我不确定这个逻辑是否改变了,但需要注意的是,上面代码中定义的 csv 字符串的格式很重要。 def csv = ''' header1,header2, header3 value1, value2, value3 '''` 不会产生预期的结果。
【解决方案2】:

有两种方法。 一种是使用收集

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

}

希望这会有所帮助!

【讨论】:

  • 您可以在 Groovy 中将整个 java 类重写为 public class CSVParser { public String[] parse( String csvLine ) { def matcher = csvLine =~ /"([^"]*)"|(?&lt;=,|^)([^,]*)(?:,|$)/ ; matcher.collect { it[1] } } }
  • 而且我仍然会使用预先编写的 CSV 解析库
  • 让我试试这个然后回复你。
  • 不,这个类根本不起作用。如果我打印它[1],它的打印会将 null 放在每个 csv 列中,除了 {} 内的内容,这对我没有帮助,抱歉!我打算接受我在第一个中提供的解决方案
猜你喜欢
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 2010-10-31
  • 2019-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多