我在Scala中阅读7z和zip文件。我这样做的方法是通过读取文件中的字节如下
val zipInputStream = new ZipInputStream(new FileInputStream(file));
var arrayBufferValues = ArrayBuffer[String]();
val buffer = new Array[Byte](1024);
var readData:Int = 0;
while({entry = zipInputStream.getNextEntry; entry != null}) {
while({readData = archiveFile.read(buffer); readData != -1}) {
content7zStream.write(buffer, 0, readData);
//println(contentBytes.toString());
arrayBufferValues += content7zStream.toString("UTF-8");
println(arrayBufferValues.mkString)
}
println("Done with processing file ====>>>>> " + Paths.get(file).getFileName + " ---- " + entry.getName);
parseFilesMap.put(Paths.get(file).getFileName + "^" + entry.getName, arrayBufferValues)
arrayBufferValues.clear();
content7zStream.close();
}
但是,当7z文件中有多个csv文件(比如大约20 MB)时,我发现很多性能问题。
处理需要数小时,而且该过程似乎仍未完成。有时我会收到OutOfMemory异常。
有更好的方法可以做到这一点,还是我错过了什么?
谢谢!
答案 0 :(得分:0)
以下是一些观察结果,希望有所帮助:
// definitely a performance killer
// try loging something shorter or comment it ouf if not really needed
println(arrayBufferValues.mkString)
20 MB的压缩文件可以是相对大量的数据,然后放入内存,即arrayBufferValues
我刚创建了一些小例子(不要在任何生产代码中执行此操作):
var arrayBufferValues = ArrayBuffer[String]()
val start = System.currentTimeMillis()
while (true) {
try {
arrayBufferValues += Random.nextString(1024)
}
catch {
case e: OutOfMemoryError ⇒
println(s"${System.currentTimeMillis() - start}ms")
System.exit(0)
}
}
在我的本地和特定设置上使用此方法,我需要在160秒内导致OutOfMemory
。我的假设是你的进程会获取一些非常大的文件,所以你可以给它额外的内存,这样就可以完成处理。
我用提供的例子玩了一下。
然后我使用以下答案调整了运行时:https://stackoverflow.com/a/2294280/7413631
以下是一些测试结果(在我的本地机器上):
-Xmx200m => 11090ms
-Xmx300m => 15295ms
-Xmx1024m => 54221ms
....
基本上合乎逻辑的是,为进程提供的内存越多,用完它就需要的时间就越多。哪种听起来像你的症状。
如果您想继续按照现在的方式处理,我的建议是为您的流程提供更多内存。
并且不要打印那么多而mkString
不需要的地方,它会杀死你的表现。