2017-01-27 1 views
0

GZIPInputStream을 통해 gzipped 파일을 읽습니다. 한 번에 많은 양의 데이터를 읽고 싶지만 GZIPInputStream에 읽는 바이트 수에 관계없이 항상 훨씬 적은 바이트 수를 읽습니다. 그것은이 경우 81,920이다 bArray의 크기와 거의 동일해야한다 예를 들어,GZIPInputStream에서 많은 바이트 수 읽기

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

바이트 판독 항상 어딘가 1,800 바이트 주변이다. 왜 이런 식으로? 이 문제를 해결할 수있는 방법이 있습니까? 실제로 많은 바이트를 읽었습니까?

+0

읽고있는 파일의 크기는 어느 정도입니까? – raam86

+0

샘플 루프 : https://github.com/scala/scala/blob/2.12.x/src/reflect/scala/reflect/io/Streamable.scala#L59 –

+0

@ som-snytt : 샘플에 gzip 라이브러리. – pythonic

답변

0

OK, 나는 해결책을 찾아 냈다. 버퍼의 크기를 취하는 GZIPInputStream 용 생성자 버전이 있습니다.

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() 
1

항상 읽기보다 적은 바이트가 반환 될 수 있으므로 일반적으로 항상 원하는만큼 루프를 반복해야합니다.

즉, GZIPInputStream에 큰 버퍼를 지정해도 주어진 요청에 채워질 것이라는 의미는 아닙니다. 그래서 그 대신, loop to drain 대신 하나 개의 읽기를 발행

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입니다 말하고 있지 않다. 나는 루프를 작성하기에는 너무 게으른 편이다.