Go语言中拷贝文件的几种常用的方式

Go语言进阶学习

共 2429字,需浏览 5分钟

 · 2022-05-13

点击上方“Go语言进阶学习”,进行关注

回复“Go语言”即可获赠Python从入门到进阶共10本电子书

连峰去天不盈尺,枯松倒挂倚绝壁。

Go语言中拷贝文件的几种常用的方式



“ 阅读本文大概需要4.2分钟 ”

简介

本篇文章将介绍Go语言中,最最最常用的3种拷贝文件的方法,这三种方法各有利弊,我们只需要在应用中选择最合适的即可,不必盲目追求性能。

方法1

第一个方法将使用标准Go库的 io.Copy()函数。以下是使用io.Copy()实现的拷贝文件代码片段:

  1. func copy(src, dst string) (int64, error) {

  2.        sourceFileStat, err := os.Stat(src)

  3.        if err != nil {

  4.                return 0, err

  5.        }

  6.        if !sourceFileStat.Mode().IsRegular() {

  7.                return 0, fmt.Errorf("%s is not a regular file", src)

  8.        }

  9.        source, err := os.Open(src)

  10.        if err != nil {

  11.                return 0, err

  12.        }

  13.        defer source.Close()

  14.        destination, err := os.Create(dst)

  15.        if err != nil {

  16.                return 0, err

  17.        }

  18.        defer destination.Close()

  19.        nBytes, err := io.Copy(destination, source)

  20.        return nBytes, err

  21. }

方法二

第二中方法是使用ioutil包中的 ioutil.WriteFile()ioutil.ReadFile(),但由于使用一次性读取文件,再一次性写入文件的方式,所以该方法不适用于大文件,容易内存溢出。

  1. input, err := ioutil.ReadFile(sourceFile)

  2.        if err != nil {

  3.                fmt.Println(err)

  4.                return

  5.        }

  6.        err = ioutil.WriteFile(destinationFile, input, 0644)

  7.        if err != nil {

  8.                fmt.Println("Error creating", destinationFile)

  9.                fmt.Println(err)

  10.                return

  11.        }

方法三

最后是使用os包中的 os.Read()os.Write(),此方法是按块读取文件,块的大小也会影响到程序的性能。

  1.  buf := make([]byte, BUFFERSIZE)

  2.        for {

  3.                n, err := source.Read(buf)

  4.                if err != nil && err != io.EOF {

  5.                        return err

  6.                }

  7.                if n == 0 {

  8.                        break

  9.                }

  10.                if _, err := destination.Write(buf[:n]); err != nil {

  11.                        return err

  12.                }

  13.        }

性能

这三种方式都能很方便的实现拷贝文件功能,那他们的性能如何呢,下面我们来尝试对比一下。三种方式都来拷贝同一个500M的文件,

以下是拷贝文件的时间明细( cp1.go是第一种方式, cp2.go是第二种方式, cp3.go是第三种方式)

  1. $ ls -l INPUT

  2. -rw-r--r--  1 mtsouk  staff  512000000 Jun  5 09:39 INPUT

  3. $ time go run cp1.go INPUT /tmp/cp1

  4. Copied 512000000 bytes!

  5. real    0m0.980s

  6. user    0m0.219s

  7. sys     0m0.719s

  8. $ time go run cp2.go INPUT /tmp/cp2

  9. real    0m1.139s

  10. user    0m0.196s

  11. sys     0m0.654s

  12. $ time go run cp3.go INPUT /tmp/cp3 1000000

  13. Copying INPUT to /tmp/cp3

  14. real    0m1.025s

  15. user    0m0.195s

  16. sys     0m0.486s

从以上数据来看3种方式的性能非常接近,但依然可以看出Go的io标准包的性能更优。


推荐阅读:

Go的并发没有它,就像iphone没有网络一样

Go图谱和技巧,有了它事半功倍

------------------- End -------------------


欢迎大家点赞转发,转载,感谢大家的相伴与支持

想加入学习群请在后台回复【入群

万水千山总是情,点个【在看】行不行

浏览 63
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报