// 提供CRC32校验和计算功能 package crc32 import ( "encoding/hex" "fmt" "hash/crc32" "io" "os" ) type CRC32Mode int const ( IEEE CRC32Mode = iota Castagnoli Koopman ) // 选择一个CRC32校验表 func tableSelect(mode CRC32Mode) *crc32.Table { switch mode { case IEEE: return crc32.IEEETable case Castagnoli: return crc32.MakeTable(crc32.Castagnoli) case Koopman: return crc32.MakeTable(crc32.Koopman) default: return crc32.IEEETable } } // 计算给定字节数组的CRC32校验和,返回字节数组 func CRC32(data []byte, mode ...CRC32Mode) []byte { crcTable := append(mode, IEEE) hasher := crc32.New(tableSelect(crcTable[0])) hasher.Write(data) return hasher.Sum(nil) } // 计算给定字节数组的CRC32校验和,返回十六进制字符串 func CRC32Hex(data []byte, mode ...CRC32Mode) string { return hex.EncodeToString(CRC32(data, mode...)) } // 计算指定文件的CRC32校验和,返回字节数组 func SumFile(file string, mode ...CRC32Mode) ([]byte, error) { f, err := os.Open(file) if err != nil { return nil, fmt.Errorf("未能打开指定文件,%w", err) } defer f.Close() crcTable := append(mode, IEEE) hasher := crc32.New(tableSelect(crcTable[0])) if _, err := io.Copy(hasher, f); err != nil { return nil, fmt.Errorf("未能读取指定文件的内容,%w", err) } return hasher.Sum(nil), nil } // 计算指定文件的CRC32校验和,返回十六进制字符串 func SumFileHex(file string, mode ...CRC32Mode) (string, error) { hash, err := SumFile(file, mode...) if err != nil { return "", err } return hex.EncodeToString(hash), nil }