导读:本文是 Go 系列的第三篇文章,我将介绍三种最流行的复制文件的方法。

本文字数:4840,阅读时长大约: 5分钟

本文是 Go 系列的第三篇文章,我将介绍三种最流行的复制文件的方法。
io.Copy()

方法一:使用 io.Copy()

io.Copy()copy()
func copy(src, dst string) (int64, error) {sourceFileStat, err := os.Stat(src)if err != nil {return 0, err}if !sourceFileStat.Mode().IsRegular() {return 0, fmt.Errorf("%s is not a regular file", src)}source, err := os.Open(src)if err != nil {return 0, err}defer source.Close()destination, err := os.Create(dst)if err != nil {return 0, err}defer destination.Close()nBytes, err := io.Copy(destination, source)return nBytes, err}
os.Stat(src)sourceFileStat.Mode().IsRegular()io.Copy(destination, source)io.Copy()nil
io.Copy()
cp1.go
$ go run cp1.goPlease provide two command line arguments!$ go run cp1.go fileCP.txt /tmp/fileCPCOPYCopied 3826 bytes!$ diff fileCP.txt /tmp/fileCPCOPY

这个方法已经非常简单了,不过它没有为开发者提供灵活性。这并不总是一件坏事,但是,有些时候,开发者可能会需要/想要告诉程序该如何读取文件。

方法二:使用 ioutil.WriteFile() 和 ioutil.ReadFile()

ioutil.ReadFile()ioutil.WriteFile()

实现代码如下:

input, err := ioutil.ReadFile(sourceFile)if err != nil {fmt.Println(err)return}err = ioutil.WriteFile(destinationFile, input, 0644)if err != nil {fmt.Println("Error creating", destinationFile)fmt.Println(err)return}
ifioutil.ReadFile()ioutil.WriteFile()
cp2.go
$ go run cp2.goPlease provide two command line arguments!$ go run cp2.go fileCP.txt /tmp/copyFileCP$ diff fileCP.txt /tmp/copyFileCP
ioutil.ReadFile()

方法三:使用 os.Read() 和 os.Write()

cp3.go
cp3.goforcopy()
buf := make([]byte, BUFFERSIZE)for {n, err := source.Read(buf)if err != nil && err != io.EOF {return err}if n == 0 {break}if _, err := destination.Write(buf[:n]); err != nil {return err}}
os.Read()bufos.Write()io.EOF
cp3.go
$ go run cp3.gousage: cp3 source destination BUFFERSIZE$ go run cp3.go fileCP.txt /tmp/buf10 10Copying fileCP.txt to /tmp/buf10$ go run cp3.go fileCP.txt /tmp/buf20 20Copying fileCP.txt to /tmp/buf20
cp3.go

运行基准测试

cp3.gotime(1)
cp1.gocp2.gocp3.go
$ ls -l INPUT-rw-r--r-- 1 mtsouk staff 512000000 Jun 5 09:39 INPUT$ time go run cp1.go INPUT /tmp/cp1Copied 512000000 bytes!real 0m0.980suser 0m0.219ssys 0m0.719s$ time go run cp2.go INPUT /tmp/cp2real 0m1.139suser 0m0.196ssys 0m0.654s$ time go run cp3.go INPUT /tmp/cp3 1000000Copying INPUT to /tmp/cp3real 0m1.025suser 0m0.195ssys 0m0.486s

我们可以看出,这三个程序的性能非常接近,这意味着 Go 标准库函数的实现非常聪明、经过了充分优化。

cp3.gocp3.go
$ ls -l INPUT-rw-r--r-- 1 mtsouk staff 512000000 Jun 5 09:39 INPUT$ time go run cp3.go INPUT /tmp/buf10 10Copying INPUT to /tmp/buf10real 6m39.721suser 1m18.457ssys 5m19.186s$ time go run cp3.go INPUT /tmp/buf20 20Copying INPUT to /tmp/buf20real 3m20.819suser 0m39.444ssys 2m40.380s$ time go run cp3.go INPUT /tmp/buf1000 1000Copying INPUT to /tmp/buf1000real 0m4.916suser 0m1.001ssys 0m3.986s
cp3.go
cp1.gocp2.gocp3.go

如果你有任何问题或反馈,请在(原文)下方发表评论或在 twitter.com 上与我(原作者)联系。

via:

本文由 原创编译, 荣誉推出

LCTT 译者 :六开箱

翻译: 68.0 篇

贡献: 77 天

2022-03-16

2022-05-31

https://linux.cn/lctt/lkxed

欢迎遵照 CC-BY-SA 协议规定转载,

如需转载,请在文章下留言 “ 转载:公众号名称”,

我们将为您添加白名单,授权“ 转载文章时可以修改”。