我正在尝试根据md5校验和创建一个检查文件重复项的程序。 不确定我是否遗漏了某些东西,但这个函数读取XCode安装程序应用程序(它有8GB)使用16GB的Ram
func search() {
unique := make(map[string]string)
files, err := ioutil.ReadDir(".")
if err != nil {
log.Println(err)
}
for _, file := range files {
fileName := file.Name()
fmt.Println("CHECKING:", fileName)
fi, err := os.Stat(fileName)
if err != nil {
fmt.Println(err)
continue
}
if fi.Mode().IsRegular() {
data, err := ioutil.ReadFile(fileName)
if err != nil {
fmt.Println(err)
continue
}
sum := md5.Sum(data)
hexDigest := hex.EncodeToString(sum[:])
if _, ok := unique[hexDigest]; ok == false {
unique[hexDigest] = fileName
} else {
fmt.Println("DUPLICATE:", fileName)
}
}
}
}
根据我的调试,问题在于文件读取 有没有更好的方法来做到这一点? 感谢
答案 0 :(得分:4)
Golang文档中有一个example,它涵盖了您的案例。
package main
import (
"crypto/md5"
"fmt"
"io"
"log"
"os"
)
func main() {
f, err := os.Open("file.txt")
if err != nil {
log.Fatal(err)
}
defer f.Close()
h := md5.New()
if _, err := io.Copy(h, f); err != nil {
log.Fatal(err)
}
fmt.Printf("%x", h.Sum(nil))
}
对于您的情况,只需确保关闭循环中的文件而不是推迟它们。或者将逻辑放入函数中。
答案 1 :(得分:3)
听起来像16GB内存是你的问题,而不是速度本身。
不要使用ReadFile将整个文件读入变量;来自Reader的io.Copy,Open给你到hash / md5提供的Writer(md5.New返回一个hash.Hash,它嵌入了一个io.Writer)。它只能一次复制一点,而不是将所有文件都拉入RAM。
这在Go的很多地方都很有用;像text/template
,compress/gzip
,net/http
这样的软件包以读者和作者的方式工作。有了它们,您通常不需要创建巨大的[]byte
或string
s;您可以将I / O接口相互连接起来,让它们为您传递内容。在垃圾收集语言中,节省内存往往也可以节省CPU工作量。