目录
-
前言
-
正文
方法一
方法二
方法三
-
结尾
前言
昨天我们介绍了 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 复制文件的操作就介绍到这里,是不是文件复制也有很多细节需要注意,比如内存问题,路漫漫其修远兮,我将上下而求索。嗯,我们明天继续,晚安各位!