0

我正在通过 GZIPInputStream 读取压缩文件。我想一次读取大量数据,但是无论我要求 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。为什么会这样?有没有办法解决这个问题,并且真的可以读取更多的字节数?

4

3 回答 3

2

如果您有大量数据,我会尝试使用 akka-streams。

  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()
于 2017-01-27T19:35:56.737 回答
1

读取可能总是返回比您要求的字节少的字节,因此通常您总是必须循环,尽可能多地读取。

换句话说,提供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,它只是为了演示。我懒得写循环了。

于 2017-01-29T00:38:55.330 回答
0

好的,我找到了解决方案。GZIPInputStream 有一个构造函数版本,它也采用缓冲区的大小。

于 2017-01-27T21:02:44.293 回答