所以我想知道如何使用scalaz-stream使用java.security.MessageDigest生成文件的摘要?
我想使用常量内存缓冲区大小(例如4KB)。我想我知道如何开始阅读文件,但我很难理解如何:
1)为每个4KB调用digest.update(buf)
,这实际上是对Java MessageDigest实例的副作用,我想这应该发生在scalaz-stream框架内。
2)最后调用digest.digest()
从scalaz-stream框架中接收计算的摘要一些如何?
我想我明白了如何开始:
import scalaz.stream._
import java.security.MessageDigest
val f = "/a/b/myfile.bin"
val bufSize = 4096
val digest = MessageDigest.getInstance("SHA-256")
Process.constant(bufSize).toSource
.through(io.fileChunkR(f, bufSize))
然后我被卡住了!
有什么提示吗?我想还必须能够在scalaz-stream Sink中包装创建,更新,检索(实际摘要计算)和摘要对象的破坏,然后调用.to()
传入那个Sink?对不起,如果我使用错误的术语,我对使用scalaz-stream完全不熟悉。我已经通过了一些例子,但我仍然在苦苦挣扎。
答案 0 :(得分:3)
由于版本0.4 scalaz-stream包含计算摘要的过程。它们位于hash
模块中,并在引擎盖下使用java.security.MessageDigest
。以下是如何使用它们的最小示例:
import scalaz.concurrent.Task
import scalaz.stream._
object Sha1Sum extends App {
val fileName = "testdata/celsius.txt"
val bufferSize = 4096
val sha1sum: Task[Option[String]] =
Process.constant(bufferSize)
.toSource
.through(io.fileChunkR(fileName, bufferSize))
.pipe(hash.sha1)
.map(sum => s"${sum.toHex} $fileName")
.runLast
sha1sum.run.foreach(println)
}
update()
和digest()
来电都包含在hash.sha1
Process1
内。
答案 1 :(得分:0)
所以我有一些工作,但它可能会改进:
import java.io._
import java.security.MessageDigest
import resource._
import scodec.bits.ByteVector
import scalaz._, Scalaz._
import scalaz.concurrent.Task
import scalaz.stream._
import scalaz.stream.io._
val f = "/a/b/myfile.bin"
val bufSize = 4096
val md = MessageDigest.getInstance("SHA-256")
def _digestResource(md: => MessageDigest): Sink[Task,ByteVector] =
resource(Task.delay(md))(md => Task.delay(()))(
md => Task.now((bytes: ByteVector) => Task.delay(md.update(bytes.toArray))))
Process.constant(4096).toSource
.through(fileChunkR(f.getAbsolutePath, 4096))
.to(_digestResource(md))
.run
.run
md.digest()
然而,在我看来应该有一个更清晰的方法来实现这一点,通过在scalaz-stream内部移动MessageDigest
的创建并让最终.run
得到{{} 1}}。
更好的答案欢迎......