io.Copy方法拷贝文件时为什么会少3K左右的字节?

ysunicom · · 1091 次点击
你构建了bufio.Writer是有缓存,默认4k的,结束的时候必须Flush一下,不然就有你问的问题,而且你的写法有问题,下面是针对你问题修改写法,还有简单的写法。 需要加writer.Flush(),同时defer关闭文件句柄要提前 ```go package main import ( "bufio" "fmt" "io" "os" ) func main() { srcFileName := "./abc.txt" dstFileName := "./abcd.txt" srcFile, err := os.Open(srcFileName) if err != nil { fmt.Println("open file err:", err) return } defer srcFile.Close() dstFile, err := os.OpenFile(dstFileName, os.O_WRONLY|os.O_CREATE, 0666) if err != nil { fmt.Println("write or create file err:", err) return } defer dstFile.Close() reader := bufio.NewReader(srcFile) writer := bufio.NewWriter(dstFile) defer writer.Flush() num, err := io.Copy(writer, reader) if err == nil { fmt.Println("完成拷贝字节数:", num) } else { fmt.Println("copy file err:", err) return } } ``` 精简写法,不需要多于的构造wirter和reader,直接使用文件句柄即可,他们满足io.Reader和io.Writer接口 ```go package main import ( "fmt" "io" "os" ) func main() { srcFileName := "./abc.txt" dstFileName := "./abcd.txt" srcFile, err := os.Open(srcFileName) if err != nil { fmt.Println("open file err:", err) return } defer srcFile.Close() dstFile, err := os.OpenFile(dstFileName, os.O_WRONLY|os.O_CREATE, 0666) if err != nil { fmt.Println("write or create file err:", err) return } defer dstFile.Close() num, err := io.Copy(dstFile, srcFile) if err == nil { fmt.Println("完成拷贝字节数:", num) } else { fmt.Println("copy file err:", err) return } } ``` 测试结果 ```go ✘ go run ./main.go 完成拷贝字节数: 7175 ✘ ls -la abc* -rw-r--r--. 1 root root 7175 Oct 2 00:20 abcd.txt -rw-r--r--. 1 root root 7175 Oct 2 00:13 abc.txt ```
#1
更多评论
太感谢了,又学到一个知识点。
#2
如果只是需要实现复制文件的功能,有一个更精简的写法。不好意思,看帖不仔细,原来楼上已经回复了同样的代码,我这里重复了。 ```go package main import ( "fmt" "io" "os" ) func CopyFile(src, dest string) (int64, error) { reader, err := os.Open(src) defer reader.Close() if err != nil { return 0, err } writer, err := os.OpenFile(dest, os.O_WRONLY|os.O_CREATE, 0666) defer writer.Close() if err != nil { return 0, err } return io.Copy(writer, reader) } func main() { srcFileName := "./abc.txt" dstFileName := "./abcd.txt" num, err := CopyFile(srcFileName, dstFileName) fmt.Println("Copied bytes:", num) if err != nil { fmt.Println(err) } } ```
#3