目录

  • 前言

  • 正文

    方法一

    方法二

    方法三

  • 结尾

前言

昨天我们介绍了 Golang 是如何“增”、“删”、“改”、“查”文件的,相信大家在掌握这些基本常规操作之后,依然意犹未尽。今天我们就补充一下,关于文件操作的另一个知识点————复制文件。

正文

复制文件也是我们开发过程中的常见操作,今天我们就来看看 Golang 语言都有哪些方法来实现文件复制。

大概有三种常用方法,它们各有千秋。

接下来,我们分别介绍。

方法一

第一种方法,使用 io/ioutil 包,分别利用它的读方法————ReadFile()和写方法————WriteFile()。 可以轻松实现从源文件中读取内容,再写入到目标文件中。下面通过一段来了解一下这个过程。

实例代码:

package main

import (
	"fmt"
	"io/ioutil"
	"os"
)

func main() {
	// 创建一个文本文件src.txt
	_, _ = os.Create("src.txt")
	// ioutil.ReadFile读取文件内容
	bytestr, err := ioutil.ReadFile("src.txt")
	if err != nil {
		fmt.Println(err)
	}
	// ioutil.WriteFile将读取到的文件写入目标文件中
	err2 := ioutil.WriteFile("dest.txt", bytestr, os.ModePerm)
	if err2 != nil {
		fmt.Println(err2)
	} else {
		fmt.Println("拷贝成功。。。")
	}
}
复制代码

代码执行结果:

拷贝成功。。。

不错,我们成功实现了文件复制功能。但是,这个方法存在一个缺点,就是我们在写入目标文件前,首先需要把源文件的内容都读取到内存中。如果是小文件还好,但是如果是大文件,非常大,比如100G,是不是常规的笔记本就读写爆表啦!

那么,有没有比较好的方法解决这个问题呢?

答案是有的,我下面就来看看。

方法二

刚才提到了复制文件时,方法一存在问题。我们应该怎样避免这样的问题呢?其实,我们在复制文件的时候,没有必要一次性将源文件内容都读取到内存中。我们一部分一部分的拷贝内容,比如申请一段内存空间2048字节,然后循环写入读取,一点点的从源文件拷贝到目标文件中。

下面我们通过一段代码来了解一下这个过程。

实例代码:

package main

import (
	"fmt"
	"io"
	"os"
)

func main() {
	// 创建一个文本文件src.txt
	_, _ = os.Create("src.txt")
	// 打开源文件
	file1, err1 := os.Open("src.txt")
	if err1 != nil {
		fmt.Println(err1)
	}

	// 打开目标文件
	file2, err2 := os.OpenFile("dest.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, os.ModePerm)
	if err2 != nil {
		fmt.Println(err2)
	}
	// 使用结束关闭文件
	defer file1.Close()
	defer file2.Close()

	bytestr := make([]byte, 2048, 2048)

	for {
		n, e := file1.Read(bytestr)
		if e == io.EOF || n == 0 {
			fmt.Println("拷贝成功。。。")
			break
		}
		// 循环写入读取到的文件
		file2.Write(bytestr[:n])
	}
}
复制代码

代码执行结果:

拷贝成功。。。

哈哈,不错,确实实现了我们最初的目标,而且还不用担心,内存的过度占用问题。那么,还有没有更加方便的方法呢?

答案是有的。请看方法三。

方法三

现在介绍一种更加简单的方法实现文件复制,不需要我们自己去管理内存,直接使用对应的 Copy() 方法就能实现文件复制。话不多,直接看代码吧。

实例代码:

package main

import (
	"fmt"
	"io"
	"os"
)

func main() {
	// 创建源文件
	_, _ = os.Create("src.txt")
	// 打开源文件
	file1, err1 := os.Open("src.txt")
	if err1 != nil {
		fmt.Println(err1)
	}

	// 创建目标文件
	file2, err2 := os.OpenFile("dest.txt", os.O_RDWR|os.O_CREATE, os.ModePerm)
	if err2 != nil {
		fmt.Println(err2)
	}
	//使用结束关闭文件
	defer file1.Close()
	defer file2.Close()
	n, e := io.Copy(file2, file1)
	if e != nil {
		fmt.Println(e)
	} else {
		fmt.Println("拷贝成功。。。,拷贝字节数:", n)
	}
	
}
复制代码

代码执行结果:

拷贝成功。。。,拷贝字节数: 0

需要指出的是,大家看到0时,不要认为是复制失败了,其实我们创建的源文件 src.txt 中,确实没有任何内容,哈哈。不要误会了,如果不放心,可以参考昨天的文章写入一些内容,再复制文件,看看这个值还是不是0。

结尾

好了,今天关于 Golang 复制文件的操作就介绍到这里,是不是文件复制也有很多细节需要注意,比如内存问题,路漫漫其修远兮,我将上下而求索。嗯,我们明天继续,晚安各位!