我尝试解析通过在目录上递归得到的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错误?
答案 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}}
会导致数据在闭包中被读取而不会在以后读取。