golang 计算大文件md5

以前介绍过用python 计算大文件的md5 值,这里将介绍使用 golang 计算大文件md5

golang 计算大文件md5

还是使用分片计算的方法

Go:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package main

import (
	"crypto/md5"
	"flag"
	"fmt"
	"io"
	"math"
	"os"
	"time"
)

const filechunk = 8192 // we settle for 8KB 8192
var file_src *string = flag.String("file", "", "The file to hash")

func main() {

	flag.Parse()
	fmt.Println("Opening file:" + *file_src)

	t1 := time.Now()

	file, err := os.Open(*file_src)

	if err != nil {
		panic(err.Error())
	}

	defer file.Close()

	// calculate the file size
	info, _ := file.Stat()

	filesize := info.Size()

	blocks := uint64(math.Ceil(float64(filesize) / float64(filechunk)))

	hash := md5.New()

	for i := uint64(0); i < blocks; i++ {
		blocksize := int(math.Min(filechunk, float64(filesize-int64(i*filechunk))))
		buf := make([]byte, blocksize)

		file.Read(buf)
		io.WriteString(hash, string(buf)) // append into the hash
	}

	fmt.Printf("%s checksum is %x\n", file.Name(), hash.Sum(nil))

	t2 := time.Now()
	fmt.Println("消耗时间:", t2.Sub(t1), "秒")

}

单独做一个包

Go:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// Package md5 computes MD5 checksum for large files
package md5

import (
	"bufio"
	"crypto/md5"
	"fmt"
	"io"
	"os"
)

const bufferSize = 65536

// MD5sum returns MD5 checksum of filename
func MD5sum(filename string) (string, error) {
	if info, err := os.Stat(filename); err != nil {
		return "", err
	} else if info.IsDir() {
		return "", nil
	}

	file, err := os.Open(filename)
	if err != nil {
		return "", err
	}
	defer file.Close()

	hash := md5.New()
	for buf, reader := make([]byte, bufferSize), bufio.NewReader(file); ; {
		n, err := reader.Read(buf)
		if err != nil {
			if err == io.EOF {
				break
			}
			return "", err
		}

		hash.Write(buf[:n])
	}

	checksum := fmt.Sprintf("%x", hash.Sum(nil))
	return checksum, nil
}

使用示例

Go:
1
2
3
4
5
6
7
8
9
10
11
12
package main

import (
    "fmt"
    "./md5"
)

func main() {
    file := "/Users/wei/Downloads/Win8pro.iso"
    md5sum, _ := md5.MD5sum(file)
    fmt.Println(md5sum)
}

Go:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package main

import (
	"bufio"
	"crypto/md5"
	"flag"
	"fmt"
	"io"
	"os"
	"time"
)

var file_src *string = flag.String("file", "", "The file to hash")

const bufferSize = 65536

// MD5sum returns MD5 checksum of filename
func MD5sum(filename string) (string, error) {
	if info, err := os.Stat(filename); err != nil {
		return "", err
	} else if info.IsDir() {
		return "", nil
	}

	file, err := os.Open(filename)
	if err != nil {
		return "", err
	}
	defer file.Close()

	hash := md5.New()
	for buf, reader := make([]byte, bufferSize), bufio.NewReader(file); ; {
		n, err := reader.Read(buf)
		if err != nil {
			if err == io.EOF {
				break
			}
			return "", err
		}

		hash.Write(buf[:n])
	}

	checksum := fmt.Sprintf("%x", hash.Sum(nil))
	return checksum, nil
}

func main() {

	flag.Parse()
	fmt.Println("Opening file:" + *file_src)

	t1 := time.Now()

	md5sum, _ := MD5sum(*file_src)
	fmt.Println(md5sum)

	t2 := time.Now()
	fmt.Println("消耗时间:", t2.Sub(t1), "秒")

}

与python 速度比较

3.8G 的文件比python 快 4秒 ,go 8.491195742s,python 12.5568759441s

本文网址: https://pylist.com/topic/126.html 转摘请注明来源

Suggested Topics

用python 正确计算文件md5

python 计算文件md5值很方便,但如果只是简单的把文件都入到内存中,大文件会导致问题,一般采用切片的方式分段计算,下面的几个函数可以很好的解决这个问题。...

Golang 服务之坑:too many open files

出现这个问题是因为服务的文件句柄超出系统限制。当Go服务程序出现这个问题,首先应该看系统设置,然后再看程序本身。...

在 Nginx 和 Golang web 上抢先体验 QUIC

QUIC(Quick UDP Internet Connection)是谷歌推出的一套基于 UDP 的传输协议,它实现了 TCP + HTTPS + HTTP/2 的功能,目的是保证可靠性的同时降低网络延迟。QUIC 是使用 UDP 协议,可以与原来的 TCP 服务不冲突。...

Golang结合OpenCC实现高效的中文简体繁体互转

之前在页面中使用简体转繁体的功能一般是使用JS对页面进行字典替换,这样可以解决大部分问题,但要进行精确的转换,才发现简繁体的转换是个复杂的过程。幸好有个非常棒的繁体转简体开源项目OpenCC可以很好的工作。...

使用Golang selenium WebDriver 自动登录微博

有时候在Golang 程序里需要读取微博的某个页面内容,提示需要登录。最简单的方法是在浏览器里登录后,直接复制Cookie 的内容,然后 http 请求带上Cookie。这样会有人工介入,不是很方便,这里借用 selenium WebDriver 来打开微博登录页面,然后自动填入用户名与密码。...

Leave a Comment