9.跨平台的文件识别
package main import ( "fmt" "io/ioutil" "github.com/h2non/filetype" ) func main() { // 堆代码 duidaima.com // 读取一个文件 buf, _ := ioutil.ReadFile("sample.jpg") // 匹配文件类型 kind, _ := filetype.Match(buf) if kind == filetype.Unknown { fmt.Println("Unknown file type") return } fmt.Printf("File type: %s. MIME: %s\n", kind.Extension, kind.MIME.Value) }输出:
File type: jpg. MIME: image/jpeg检查文件类别
package main import ( "fmt" "io/ioutil" "github.com/h2non/filetype" ) func main() { // 堆代码 duidaima.com // 读取一个文件 buf, _ := ioutil.ReadFile("sample.jpg") // 检查是否是图片 if filetype.IsImage(buf) { fmt.Println("File is an image") } else { fmt.Println("Not an image") } }输出:
package main import ( "fmt" "github.com/h2non/filetype" ) func main() { // 检查是否支持某个扩展名 if filetype.IsSupported("jpg") { fmt.Println("Extension supported") } else { fmt.Println("Extension not supported") } // 检查是否支持某个 MIME 类型 if filetype.IsMIMESupported("image/jpeg") { fmt.Println("MIME type supported") } else { fmt.Println("MIME type not supported") } }输出:
Extension supported MIME type supported
package main import ( "fmt" "github.com/h2non/filetype" ) // 定义一个新的类型 var fooType = filetype.NewType("foo", "foo/foo") // 定义一个新的匹配器 func fooMatcher(buf []byte) bool { return len(buf) > 1 && buf[0] == 0x01 && buf[1] == 0x02 } func main() { // 注册新的匹配器和类型 filetype.AddMatcher(fooType, fooMatcher) // 检查是否支持新的扩展名 if filetype.IsSupported("foo") { fmt.Println("New supported type: foo") } // 检查是否支持新的 MIME 类型 if filetype.IsMIMESupported("foo/foo") { fmt.Println("New supported MIME type: foo/foo") } // 尝试匹配新的类型 fooFile := []byte{0x01, 0x02} kind, _ := filetype.Match(fooFile) if kind == filetype.Unknown { fmt.Println("Unknown file type") } else { fmt.Printf("File type matched: %s\n", kind.Extension) } }输出:
New supported type: foo New supported MIME type: foo/foo File type matched: foo优缺点分析,和标准库 http.DetectContentType 的对比
2.可能存在一些未知或不常见格式的检测不准确或不支持的情况(但比标准库的好很多)
package main import ( "io/ioutil" "testing" "github.com/h2non/filetype" ) // 读取一个文件并返回字节切片 func readFile(filename string) []byte { buf, _ := ioutil.ReadFile(filename) return buf } // 测试文件类型检测的性能 func BenchmarkMatch(b *testing.B) { // 读取一个图片文件 buf := readFile("sample.jpg") // 重置计时器 b.ResetTimer() // 循环执行 b.N 次 for i := 0; i < b.N; i++ { // 调用 filetype.Match 函数 filetype.Match(buf) } } // 测试标准库函数的性能 func BenchmarkDetect(b *testing.B) { // 读取一个图片文件 buf := readFile("sample.jpg") // 重置计时器 b.ResetTimer() // 循环执行 b.N 次 for i := 0; i < b.N; i++ { // 调用 http.DetectContentType 函数 http.DetectContentType(buf) } }然后我们运行 go test -bench=. -benchmem 来执行基准测试,得到以下输出:
goos: darwin goarch: arm64 pkg: test/filetype BenchmarkMatch-8 268744659 4.381 ns/op 0 B/op 0 allocs/op BenchmarkDetect-8 8401593 142.1 ns/op 0 B/op 0 allocs/op PASS ok test/filetype 3.478s从输出中我们可以看到,filetype 的性能远高于标准库。(可能和标准库读取前 512 字节有关,而 filetype 只需要读取前 262 个字节)