【问题标题】:Gzip file reader ScalaGzip 文件阅读器 Scala
【发布时间】:2013-11-05 17:32:25
【问题描述】:

我是 scala 的新手,并且可以即时解决问题。我有一个程序需要读取各种大小的 Gzip 文件 - 20KB、2MB 和 150MB(是的,压缩文件是 150MB)。我认为没有一种不同的方法来读取不同的文件,而是一种标准的方法。我看到的大多数方法都使用 64MB 的缓冲区大小来逐行读取文件?什么是最好的(读作,*最快和干净的内存 * 方法)来做到这一点?

提前感谢您的帮助!

更新 1:

阅读率大大提高。(我什至会分享我的业力点)谢谢! :)

但是,我注意到,由于我的每个文件都有大约 10K 行,在将它们写入文件时,在写入文件之前将字符串迭代器转换为字符串需要很长时间。我可以做两种方法,

  1. 逐行迭代并逐行写入文件。
  2. 逐行迭代以将行转换为大字符串(“\n”分隔)并将该大字符串写入文件。

我假设 [2] 会更快。所以,这就是写作的目的,

var processedLines = linesFromGzip(new File(fileName)).map(line => MyFunction(line))

var  outFile = Resource.fromFile(outFileName)

outFile.write(processedLines.mkString("\n"))  // severe overhead -> processedLines.mkString("\n")

此外,我的分析(通过评论 write() 表明,将 processedLines 转换为单个大字符串并不需要太多时间 - 它需要接近一秒钟 - 这是巨大的成本对于我的应用程序。最好的(再次清理没有任何内存泄漏)方法来做到这一点。

【问题讨论】:

  • 你说的干净的内存是什么意思?
  • 每种类型都有大约 10K 个文件。我希望我的进程可以线性缩放而没有任何内存泄漏。例如:在 Python 中,readlines() 使文件在内存中保持打开状态,这可能会导致内存开销。我不想得到那种类型的泄漏(显然我们没有内存来处理内存中的所有这些文件)

标签: performance scala optimization file-io gzip


【解决方案1】:

您的内存问题是由打开的文件过多引起的,而不是文件的大小。您需要一种机制来在读取每个文件后自动关闭它。

一种方法:

      // this Source closes at the end of iteration                        
      implicit def closingSource(source: Source) = new {
        val lines = source.getLines()
        var isOpen = true
        def closeAfterGetLines() = new Iterator[String] {
          def hasNext = isOpen && hasNextAndCloseIfDone
          def next() = {
            val line = lines.next()
            hasNextAndCloseIfDone
            line
          }
          private def hasNextAndCloseIfDone = if (lines.hasNext) true else { source.close() ; isOpen = false ; false }
        }
      }

然后你使用 gzip 阅读器:

def gzInputStream(gzipFile: File) = new GZIPInputStream(new BufferedInputStream(new FileInputStream(gzipFile)))

def linesFomGzip(gzipFile: File): Iterator[String] = {
            Source.fromInputStream(gzInputStream(gzipFile)).closeAfterGetLines()
          }

请注意,仅当迭代完成时才会关闭文件,即读取整个文件。如果(出于某种原因)您没有读取整个文件,则需要手动关闭该文件。

【讨论】:

  • 你能告诉我这个类“gzInputStream”属于哪个库吗?
  • 在响应中添加了gzInputStream的定义。
  • 将文件作为字符串迭代器读取会导致写入时产生开销。正如我在这里提到的-> stackoverflow.com/questions/19804928/… 有更好的选择@adrian 吗?谢谢!
  • 你能解释一下拥有这个hasNextAndCloseIfDone这个的逻辑吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-16
  • 1970-01-01
  • 1970-01-01
  • 2019-08-29
  • 1970-01-01
  • 2011-05-05
  • 1970-01-01
相关资源
最近更新 更多