我需要在Scala中读取一个大文件并以k位为单位处理它(k通常可以是65536).作为一个简单的例子(但不是我想要的):
文件块是(f1, f2, ... fk).
我想计算 SHA256(f1)+SHA256(f2)+...+ SHA256(fk)
这种计算可以仅使用恒定存储和当前块递增地完成,而不需要其他块.
阅读文件的最佳方法是什么?(也许是使用延续的东西?)
编辑:链接的问题解决了问题但不总是,因为我正在查看的文件包含二进制数据.
这是一种使用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,Flow和Sink.这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)