解析多个文件时CsvParser流已关闭错误

时间:2014-04-14 10:52:59

标签: csv groovy ioexception

我尝试解析通过在目录上递归得到的CSV文件列表。下面的代码只打印一行,然后存在Stream Closed Error:

def stageDir = new File(STAGE_DIR), listOfFiles = [], filesData = []
// Get the list of files
stageDir.eachFileRecurse(FileType.FILES) { file ->
   listOfFiles << file
}

// Start parsing each CSV file in the list
listOfFiles.each { file ->
   def csvData = file.withReader {
      new CsvParser().parse( it , separator: CSV_SEPARATOR )
   }

   // Here i put the returned csvData (of type CsvIterator) in the filesData
   filesData.add(csvData)
}

// I checked filesData and it's not empty, so i iterate over it.

// HERE I GET : Stream Closed error
// I'm just trying to test by printing the first line of myIt 
// (but is there a more efficient way to iterate over CsvIterator ?)
for (myIt in filesData) {
   println myIt[0].ID + " " + myIt[0].NAME
}

是否有更好的方法将CsvParser与多个文件一起使用并避免Stream Closed错误?

2 个答案:

答案 0 :(得分:2)

当天回来,当文件关闭并且您尝试从中读取时,异常是预期的结果。

但不要害怕! OpenCSV项目有一个新的活跃开发人员Maciek,他不仅将项目更新为Java 7(因为不再支持5和6)他已将CSVReader更改为不抛出IOException但要安静地处理它。

我们已在Sourceforge as version 3.0上推出此版本。请随意测试并将xlson库更新到新版本。

我不得不说我很荣幸看到我们的工作在其他项目中结束。它有点像吉他制造商,发现一个着名的摇滚乐队使用你的吉他。

答案 1 :(得分:1)

您不会将filesData添加到已解析的数据中,但实际上new File('').withReader{}返回的结果可能是流或其他任何内容。而是尝试:

listOfFiles.each { file ->
   def csvData = file.withReader {
      filesData.add(new CsvParser().parse( it , separator: CSV_SEPARATOR ))
   }
}

<强>更新

我也怀疑你是否正确迭代filesData。在每个循环中,myIt不是数据行,而是从Iterable方法返回的parse实例。现在无法进行实验,但也许应该是。

for (myIt in filesData) {
   myIt.each { rowIt ->
     println rowIt.ID + " " + rowIt.NAME
   }
}

更新2

groovy控制台的工作示例

@Grab( 'com.xlson.groovycsv:groovycsv:1.0' )
import com.xlson.groovycsv.CsvParser

def csv1 = '''ID,NAME,ADDRESS
1,n1,a1
2,n2,a2
3,n3,a3'''

def csv2 = '''ID,NAME,ADDRESS
4,n4,a4
5,n5,a5
6,n6,a6
'''
def listOfFiles = [csv1, csv2]
def filesData = []

listOfFiles.each { filesData.add(new CsvParser().parse( it , separator: ',' )) }

filesData.each { d ->
    d.each { r ->
        println "$r.ID $r.NAME"
    }
}

您需要做的是检查您提供的示例中是否所有文件操作都顺利运行。

更新3:D

以下是带有重现错误的示例代码:

@Grab( 'com.xlson.groovycsv:groovycsv:1.0' )
import com.xlson.groovycsv.CsvParser

def f1
def f2 

try {
    f1 = File.createTempFile("temp1",".csv")
    f2 = File.createTempFile("temp2",".csv")
    f1.text = '''ID,NAME,ADDRESS
1,n1,a1
2,n2,a2
3,n3,a3
'''

    f2.text = '''ID,NAME,ADDRESS
4,n4,a4
5,n5,a5
6,n6,a6
'''
    def listOfFiles = [f1, f2]
    def filesData = []

    listOfFiles.each { f ->
        f.withReader { r -> 
            def data = new CsvParser().parse( r , separator: ',' )
            filesData.add(data)
        }
    }

    filesData.each { d ->
        d.each { r ->
            println "$r.ID $r.NAME"
        }
    }
} finally {
    f1?.delete()
    f2?.delete()
}

现在......这里发生了什么。 withReader parse CsvParser方法调用r传递withReader(读取器)对象的方法。但是r关闭并不是急切地评估,而是懒惰。然后在打印解析数据的位置读取EOF,并且groovy检测到3,n3,a3\n'''自动关闭流(可以通过将3,n3,a3'''更改为au.com.bytecode.opencsv.CSVReader轻松验证但是,类getNextLine()Stream closed方法)并不检查流是否已关闭并尝试读取它会导致CSVReader异常。实际上这是一个错误filesData.add(data) 上课。

纠正它您需要将懒惰的阅读更改为渴望。这可以通过更改这行代码来完成:

filesData.add(data.toList())

到此:

{{1}}

会导致数据在闭包中被读取而不会在以后读取。