```go
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func main() {
srcFileName := "d:/abc.txt"
dstFileName := "d:/abcd.txt"
srcFile, err := os.Open(srcFileName)
if err != nil {
fmt.Println("open file err:", err)
return
}
reader := bufio.NewReader(srcFile)
dstFile, err := os.OpenFile(dstFileName, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
fmt.Println("write or create file err:", err)
return
}
writer := bufio.NewWriter(dstFile)
num, err := io.Copy(writer, reader)
if err == nil {
fmt.Println("完成拷贝字节数:", num)
} else {
fmt.Println("copy file err:", err)
return
}
defer srcFile.Close()
defer dstFile.Close()
}
```
执行后:显示操作的字节数是正确的,但目标文件内容和大小不正确,少了3K左右的字节,这是为什么?![问题.jpg](https://static.studygolang.com/191007/7ab5b992faf5ad6de4c133d84c994e2b.jpg)
更多评论
你构建了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
如果只是需要实现复制文件的功能,有一个更精简的写法。不好意思,看帖不仔细,原来楼上已经回复了同样的代码,我这里重复了。
```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