-
Notifications
You must be signed in to change notification settings - Fork 3
/
readercomp.go
92 lines (79 loc) · 1.86 KB
/
readercomp.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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// Package readercomp provides comparison functions for readers or more specific for comparing file contents
package readercomp
import (
"bytes"
"io"
"os"
)
// Equal tests two finite reader streams for equality by comparing batches up to bufSize
func Equal(r1, r2 io.Reader, bufSize int) (bool, error) {
b1 := make([]byte, bufSize)
b2 := make([]byte, bufSize)
for {
n1, err1 := r1.Read(b1)
n2, err2 := r2.Read(b2)
if err1 != nil && err1 != io.EOF {
return false, err1
}
if err2 != nil && err2 != io.EOF {
return false, err2
}
// Catch up with r2
for n1 < n2 {
var more int
more, err1 = r1.Read(b1[n1:n2])
n1 += more
if err1 == io.EOF {
break
} else if err1 != nil {
return false, err1
}
}
// Catch up with r1
for n2 < n1 {
var more int
more, err2 = r2.Read(b2[n2:n1])
n2 += more
if err2 == io.EOF {
break
} else if err2 != nil {
return false, err2
}
}
if !bytes.Equal(b1[:n1], b2[:n2]) {
return false, nil
}
// We asserted before that err1 / err2 are either nil or io.EOF - if both are io.EOF we are finished
if err1 == io.EOF && err2 == io.EOF {
return true, nil
}
// Continue anyway, either err1 or err2 could be io.EOF and the other nil, which is allowed and could settle
// on the next call to Read
}
}
// FilesEqual tests two files for equality (same content)
func FilesEqual(name1, name2 string) (bool, error) {
f1Info, err := os.Stat(name1)
if err != nil {
return false, err
}
f2Info, err := os.Stat(name2)
if err != nil {
return false, err
}
if f1Info.Size() != f2Info.Size() {
return false, nil
}
f1, err := os.Open(name1)
if err != nil {
return false, err
}
defer f1.Close()
f2, err := os.Open(name2)
if err != nil {
return false, err
}
defer f2.Close()
// 64 KiB buffers seem to be most performant with larger files
return Equal(f1, f2, 64*1024)
}