在顺序块中读取非常大的文件(~1 TB)

Jus*_*s12 7 scala large-files

我需要在Scala中读取一个大文件并以k位为单位处理它(k通常可以是65536).作为一个简单的例子(但不是我想要的):

文件块是(f1, f2, ... fk).

我想计算 SHA256(f1)+SHA256(f2)+...+ SHA256(fk)

这种计算可以仅使用恒定存储和当前块递增地完成,而不需要其他块.

阅读文件的最佳方法是什么?(也许是使用延续的东西?)

编辑:链接的问题解决了问题但不总是,因为我正在查看的文件包含二进制数据.

Bri*_*ian 5

这是一种使用Akka Streams的方法.这使用常量内存,并且可以在读取时处理文件块.

有关详细信息,请参阅本页底部的"Streaming File IO".http://doc.akka.io/docs/akka-stream-and-http-experimental/1.0-RC3/scala/stream-io.html

从一个简单的build.sbt文件开始:

scalaVersion := "2.11.6"

libraryDependencies ++= Seq(
        "com.typesafe.akka" %% "akka-stream-experimental" % "1.0-RC3"
)
Run Code Online (Sandbox Code Playgroud)

有趣的部分是Source,FlowSink.这Source是一个SynchronousFileSource读入大块文件的大文件65536.阿ByteString块大小是由所发射的Source,并通过一个所消耗Flow,其计算每个块的SHA256散列.最后,Sink消耗输出Flow并输出字节数组.你想要转换它们并使用a fold求它们得到总和.

import akka.stream.io._
import java.io.File
import scala.concurrent.Future
import akka.stream.scaladsl._
import akka.actor.ActorSystem
import akka.stream.ActorFlowMaterializer
import java.security.MessageDigest

object LargeFile extends App{
  implicit val system = ActorSystem("Sys")
  import system.dispatcher
  implicit val materializer = ActorFlowMaterializer()

   val file = new File("<path to large file>")

   val fileSource = SynchronousFileSource(file, 65536)

   val shaFlow = fileSource.map(chunk => sha256(chunk.toString))

   shaFlow.to(Sink.foreach(println(_))).run//TODO - Convert the byte[] and sum them using fold

   def sha256(s: String) = {
     val  messageDigest = MessageDigest.getInstance("SHA-256")
     messageDigest.digest(s.getBytes("UTF-8"))
   }
}
Run Code Online (Sandbox Code Playgroud)

BYTE ARRAYS!

> run
[info] Running LargeFile 
[B@3d0587a6
[B@360cc296
[B@7fbb2192
...
Run Code Online (Sandbox Code Playgroud)