file - Go中如何一步返回hash和bytes?

标签 file go hash

我试图了解如何读取文件内容、计算其哈希值并一次性返回其字节。到目前为止,我分两步进行,例如

// calculate file checksum
hasher := sha256.New()
f, err := os.Open(fname)
if err != nil {
    msg := fmt.Sprintf("Unable to open file %s, %v", fname, err)
    panic(msg)
}
defer f.Close()
b, err := io.Copy(hasher, f)
if err != nil {
    panic(err)
}
cksum := hex.EncodeToString(hasher.Sum(nil))

// read again (!!!) to get data as bytes array
data, err := ioutil.ReadFile(fname)

显然这不是执行此操作的最有效方法,因为读取发生了两次,一次在副本中传递给哈希器,另一次在 ioutil 中读取文件并返回字节列表。我正在努力理解如何将这些步骤组合在一起并一次性完成,一次读取数据,计算任何哈希并将其与字节列表一起返回到另一层。

最佳答案

如果你想读取一个文件,而不在内存中创建整个文件的副本,同时计算它的哈希值,你可以使用 TeeReader 来实现。 :

hasher := sha256.New()
f, err := os.Open(fname)
data := io.TeeReader(f, hasher)
// Now read from data as usual, which is still a stream.

这里发生的是,从 data(它是一个 Reader,就像文件对象 f 一样)读取的任何字节都会也被推送到 hasher

但是请注意,hasher 只有在您通过 data 读取整个文件后才会生成正确的哈希值,直到那时才生成。因此,如果您在决定是否要读取文件之前需要哈希,您可以选择分两次进行(例如像现在这样),或者始终读取文件但丢弃如果哈希检查失败则返回结果。

如果您分两次读取文件,您当然可以将整个文件数据缓冲到内存中的字节缓冲区中。但是,操作系统通常会将您刚刚读取的文件缓存在 RAM 中(如果可能的话),因此您自己执行缓冲的两次传递解决方案而不是仅对文件执行两次传递的性能优势可能可以忽略不计。

关于file - Go中如何一步返回hash和bytes?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41947307/

相关文章:

javascript - "Cross origin requests are only supported for HTTP."加载本地文件时出错

mysql - Gorm处理HasOne关系

hash - 那是 Perl 6 哈希还是 block ?

perl - 在 Perl 中对巨大的哈希进行排序

windows - 为什么我只能在 Windows 上使用 Tie::File 打开 2045 个文件?

c# - FileInfo.LastWriteTime 怎么可能早于 FileInfo.CreationTime?

c - 从字符串中删除尾部空格 (char*)

去生成替代语句位置

arrays - 在 MongoDB Golang 中存储 slice 和嵌套结构

jquery - 获取 URL 哈希位置,并在 jQuery 中使用它