簡體   English   中英

從GZIPInputStream讀取大量字節

[英]Reading large number of bytes from GZIPInputStream

我正在通過GZIPInputStream閱讀gzip壓縮文件。 我想一次讀取大量數據,但是無論我要求GZIPInputStream讀取多少字節,它總是讀取的字節數要少得多。 例如,

val bArray = new Array[Byte](81920)
val fis = new FileInputStream(new File(inputFileName))
val gis = new GZIPInputStream(fis)
val bytesRead =  gis.read(bArray)

讀取的字節總是在1800字節左右,而它應該幾乎等於bArray的大小,在這種情況下為81920。 為什么會這樣呢? 有沒有辦法解決此問題,並且確實讀取了更多字節?

如果您有大量數據,我會嘗試使用akka流。

  implicit val system = ActorSystem()
  implicit val ec = system.dispatcher
  implicit val materializer = ActorMaterializer()

  val fis = new FileInputStream(new File(""))
  val gis = new GZIPInputStream(fis) 
  val bfs: BufferedSource = Source.fromInputStream(gis)

bfs公開用於流處理的Flow api。

您還可以從中獲得一個流:

val ss: Stream[String] = bfs.bufferedReader().lines()

讀取返回的字節可能總是少於您要求的字節,因此通常您總是必須循環讀取任意數量的字節。

換句話說,給GZIPInputStream一個大緩沖區並不意味着它將在給定請求中被填充。

import java.util.zip.GZIPInputStream
import java.io.FileInputStream
import java.io.File
import java.io.InputStream
import java.io.FilterInputStream

object Unzipped extends App {
  val inputFileName = "/tmp/sss.gz"
  val bArray = new Array[Byte](80 * 1024)
  val fis = new FileInputStream(new File(inputFileName))
  val stingy = new StingyInputStream(fis)
  val gis = new GZIPInputStream(stingy, 80 * 1024)
  val bytesRead = gis.read(bArray, 0, bArray.length)
  println(bytesRead)
}

class StingyInputStream(is: InputStream) extends FilterInputStream(is) {
  override def read(b: Array[Byte], off: Int, len: Int) = {
    val n = len.min(1024)
    super.read(b, off, n)
  }
}

因此,請循環執行以耗盡資源,而不是發出一個讀取:

  import reflect.io.Streamable.Bytes
  val sb = new Bytes {
    override val length = 80 * 1024L
    override val inputStream = gis
  }
  val res = sb.toByteArray()
  println(res.length)  // your explicit length

我並不是說這是要使用的API,只是為了演示。 我懶得寫一個循環。

好的,我找到了解決方案。 GZIPInputStream有一個構造函數版本,該版本也采用緩沖區的大小。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM