【问题标题】:Read from GZIPInputStream to String without using Source不使用 Source 从 GZIPInputStream 读取到 String
【发布时间】:2018-04-17 08:32:43
【问题描述】:

我正在使用 Scala。我需要读取一个大的 gzip 文件并将其转换为字符串。我需要删除第一行。 这就是我读取文件的方式:

val fis = new FileInputStream(filename)
val gz  = new GZIPInputStream(fis)

然后我尝试了这个Source.fromInputStream(gz).getLines.drop(1).mkString("") .但它会导致内存不足错误。

因此,我想到了逐行读取,也许将其放入字节数组中。然后我可以把它转换成一个字符串。

但我不知道该怎么做。有什么建议吗?或者也欢迎任何更好的方法。

【问题讨论】:

  • 查看内存映射 IO。此外,StringBuffer 可能会有所帮助。
  • 你得到的OOM是因为文件的内容不适合内存。如果您将其读入数组、列表或任何其他容器,则无关紧要。您要么需要更多内存,要么想办法在不将全部内容存入内存的情况下做您需要的事情。
  • gunziped 的文件有多大?
  • @dkim 大约 250MB
  • 检查最大 JVM 堆大小并在必要时增加它可能会有所帮助。请参阅 1) How is the default java heap size determined? 和 2) Increase JVM heap size for Scala?

标签: scala file


【解决方案1】:

如果您的 gzip 文件很大,您可以使用 BufferedReader。这是一个例子。它将所有字符从 gzip 压缩文件复制到未压缩文件,但它跳过第一行

import java.util.zip.GZIPInputStream
import java.io._
import java.nio.charset.StandardCharsets

import scala.annotation.tailrec
import scala.util.Try

val bufferSize = 4096
val pathToGzFile = "/tmp/text.txt.gz"
val pathToOutputFile = "/tmp/text_without_first_line.txt"
val charset = StandardCharsets.UTF_8

val inStream = new FileInputStream(pathToGzFile)
val outStream = new FileOutputStream(pathToOutputFile)

try {
  val inGzipStream = new GZIPInputStream(inStream)
  val inReader = new InputStreamReader(inGzipStream, charset)
  val outWriter = new OutputStreamWriter(outStream, charset)
  val bufferedReader = new BufferedReader(inReader)

  val closeables =  Array[Closeable](inGzipStream, inReader, 
    outWriter, bufferedReader)
  // Read first line, so copy method will not get this - it will be skipped
  val firstLine = bufferedReader.readLine()
  println(s"First line: $firstLine")

  @tailrec
  def copy(in: Reader, out: Writer, buffer: Array[Char]): Unit = {
    // Copy while it's not end of file
    val readChars = in.read(buffer, 0, buffer.length)
    if (readChars > 0) {
      out.write(buffer, 0, readChars)
      copy(in, out, buffer)
    }
  }

  // Copy chars from bufferReader to outWriter using buffer
  copy(bufferedReader, outWriter, Array.ofDim[Char](bufferSize))

  // Close all closeabes
  closeables.foreach(c => Try(c.close()))
}
finally {
  Try(inStream.close())
  Try(outStream.close())
}

【讨论】:

    猜你喜欢
    • 2016-06-17
    • 1970-01-01
    • 1970-01-01
    • 2010-11-07
    • 1970-01-01
    • 1970-01-01
    • 2020-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多