Scala 用于完成随机访问文件读取的指令

Scala 用于完成随机访问文件读取的指令,scala,akka-stream,akka-http,Scala,Akka Stream,Akka Http,我有一个大的数据文件,并用该文件的很小部分作为Array[Byte] 该指令是: get { dataRepo.load(param).map(data => complete( HttpResponse( entity = HttpEntity(myContentType, data), headers = List(gzipContentEncoding) ) ) ).getOrElse(complete(

我有一个大的数据文件,并用该文件的很小部分作为
Array[Byte]

该指令是:

get {
  dataRepo.load(param).map(data =>
    complete(
      HttpResponse(
        entity = HttpEntity(myContentType, data),
        headers = List(gzipContentEncoding)
      )
    )
  ).getOrElse(complete(HttpResponse(status = StatusCodes.NoContent)))
}
其中,
dataRepo.load
是一个函数,其内容如下:

val pointers: Option[Long, Int] = calculateFilePointers(param)
pointers.map { case (index, length) =>
  val dataReader = new RandomAccessFile(dataFile, "r")
  dataReader.seek(index)
  val data = Array.ofDim[Byte](length)
  dataReader.readFully(data)
  data
}

有没有一种更有效的方法将随机访问文件直接回传到响应中,而不必先完全读取?

您可以创建一个
迭代器[Array[Byte]
,一次读取文件的块,而不是将数据读入
数组[Byte]

val dataReader = new RandomAccessFile(dataFile, 'r')

val chunkSize = 1024

Iterator
  .range(index, index + length, chunkSize)
  .map {  currentIndex =>
    val currentBytes = 
      Array.ofDim[Byte](Math.min(chunkSize, length - currentIndex))

    dataReader seek currentIndex
    dataReader readFully currentBytes

    currentBytes
  } 
该迭代器现在可以为akka
源提供数据:

val source : Source[Array[Byte], _] = 
  Source fromIterator (() => dataRepo.load(param))
然后可以向HttpEntity提供:

val byteStrSource : Source[ByteString, _] = source.map(ByteString.apply)

val httpEntity = HttpEntity(myContentType, byteStrSource)
现在,每个客户端一次只使用1024字节的内存,而不是读取文件的全部长度。这将使您的服务器在处理多个并发请求时更加高效,并允许您的
dataRepo.load
立即返回一个惰性
值,而不是使用
未来