本文将向你展示如何快速确定两个文件是否相同。还将为你提供一种找到两者之间差异的方法。
比较两个文件
Golang 版本
1.12.1
前言
本文将向你展示如何快速确定两个文件是否相同。还将为你提供一种找到两者之间差异的方法。
实现
package main
import (
"bufio"
"crypto/md5"
"fmt"
"io"
"os"
)
var data = []struct {
name string
cont string
perm os.FileMode
}{
{"test1.file", "Hello\nGolang is great", 0666},
{"test2.file", "Hello\nGolang is great", 0666},
{"test3.file", "Not matching\nGolang is great\nLast line",
0666},
}
func main() {
files := []*os.File{}
for _, fData := range data {
f, err := os.Create(fData.name)
if err != nil {
panic(err)
}
defer f.Close()
_, err = io.WriteString(f, fData.cont)
if err != nil {
panic(err)
}
files = append(files, f)
}
// 通过校验和比较
checksums := []string{}
for _, f := range files {
f.Seek(0, 0) // 重置文件的开头
sum, err := getMD5SumString(f)
if err != nil {
panic(err)
}
checksums = append(checksums, sum)
}
fmt.Println("### 通过校验和比较 ###")
compareCheckSum(checksums[0], checksums[1])
compareCheckSum(checksums[0], checksums[2])
fmt.Println("### 逐行比较 ###")
files[0].Seek(0, 0)
files[2].Seek(0, 0)
compareFileByLine(files[0], files[2])
// 清理
for _, val := range data {
os.Remove(val.name)
}
}
func getMD5SumString(f *os.File) (string, error) {
file1Sum := md5.New()
_, err := io.Copy(file1Sum, f)
if err != nil {
return "", err
}
return fmt.Sprintf("%X", file1Sum.Sum(nil)), nil
}
func compareCheckSum(sum1, sum2 string) {
match := "match"
if sum1 != sum2 {
match = " does not match"
}
fmt.Printf("Sum: %s and Sum: %s %s\n", sum1, sum2, match)
}
func compareLines(line1, line2 string) {
sign := "o"
if line1 != line2 {
sign = "x"
}
fmt.Printf("%s | %s | %s \n", sign, line1, line2)
}
func compareFileByLine(f1, f2 *os.File) {
sc1 := bufio.NewScanner(f1)
sc2 := bufio.NewScanner(f2)
for {
sc1Bool := sc1.Scan()
sc2Bool := sc2.Scan()
if !sc1Bool && !sc2Bool {
break
}
compareLines(sc1.Text(), sc2.Text())
}
}
$ go run main.go
### 通过校验和比较 ###
Sum: 5A07C1538087CD5B5C365DE52970E0A3 and Sum: 5A07C1538087CD5B5C365DE52970E0A3 match
Sum: 5A07C1538087CD5B5C365DE52970E0A3 and Sum: FED2EADA5D1D1EBF745DFDC7D1385E6C does not match
### 逐行比较 ###
x | Hello | Not matching
o | Golang is great | Golang is great
x | | Last line
原理
两个文件的比较可以通过几种方式完成。 本文介绍了两种基本的方法。 第一个是通过创建文件的校验来比较整个文件。
第二种方法逐行比较文件(在本例中为字符串内容)。 如果不匹配,则标记x
符号。 这与比较二进制内容的方式相同,但需要按字节块(字节切片)扫描文件。