手动实现

思路就是:先创立一个切片 而后通过Read办法操作源文件把数据读到切片中,而后再通过Write办法把切片外面的数据写到指标文件外面。

具体怎么应用呢?
举个例子:
如果我有一个文件test.txt,而后我想要把这个文件复制到destination.txt,就能够这样写:

package mainimport (    "fmt"    "io"    "os")func main() {    // 拷贝文件    srcFile := "/Users/liberhome/GolandProjects/awesomeProject/I-package/April28_Go_io/test.txt"    destFile := "destination.txt"    total, err := copyFile1(srcFile, destFile) //函数的具体实现在上面    fmt.Println(total, err)}func copyFile1(srcFile, destFile string) (int, error) { //返回值是实现拷贝数据的字节数&err    file1, err := os.Open(srcFile) //这里读 所以用open就足够了    if err != nil {        return 0, err    }    file2, err := os.OpenFile(destFile, os.O_WRONLY|os.O_CREATE, os.ModePerm) //这里要写文件 所以须要用到OpenFile    if err != nil {        return 0, err    }    // 敞开文件    defer file1.Close()    defer file2.Close()    //读写文件    bs := make([]byte, 1024, 1024)//用make发明切片    n := -1    //每次读取的字节数    total := 0 //读取的总数量    for {        n, err = file1.Read(bs)        if err == io.EOF || n == 0 {            fmt.Println("copy is complete")            break        } else if err != nil {            fmt.Println("error happen")            return total, err        }        total += n        file2.Write(bs[:n])    }    return total, nil}

当然了,这段代码不仅能够复制txt文件,其余类型,比方png什么的都不在话下,毕竟是通过字节传递的。

以上就是手动实现copy,当然这太麻烦了,理论工作中很少这么用,之所以放在这里,是为了更深层的了解他的实现原理,万变不离其宗,这就是宗。

接下来介绍一下理论罕用的

库函数实现

io.Copy()办法实现

func Copy(dst Writer, src Reader) (written int64, err error)  {}

这个函数须要两个参数,第一个是向外写的目标对象,第二个是读进来的对象;返回值有两个,一个是复制的总数据量,一个是谬误。须要留神的是,如果胜利拷贝,返回值是nil 不是EOF。

具体怎么应用呢?
还是复制下面例子中的文件,代码如下

package mainimport (    "fmt"    "io"    "os")func main() {    // 拷贝文件    srcFile := "/Users/liberhome/GolandProjects/awesomeProject/I-package/April28_Go_io/test.txt"    destFile := "destination2.txt"    //total, err := copyFile1(srcFile, destFile) //函数的具体实现在上面    total, err := copyFile2(srcFile, destFile) //函数的具体实现在上面    fmt.Println(total, err)}func copyFile1(srcFile, destFile string) (int, error) { //返回值是实现拷贝数据的字节数&err    file1, err := os.Open(srcFile) //这里读 所以用open就足够了    if err != nil {        return 0, err    }    file2, err := os.OpenFile(destFile, os.O_WRONLY|os.O_CREATE, os.ModePerm) //这里要写文件 所以须要用到OpenFile    if err != nil {        return 0, err    }    // 敞开文件    defer file1.Close()    defer file2.Close()    //读写文件    bs := make([]byte, 1024, 1024)    n := -1    //每次读取的字节数    total := 0 //读取的总数量    for {        n, err = file1.Read(bs)        if err == io.EOF || n == 0 {            fmt.Println("copy is complete")            break        } else if err != nil {            fmt.Println("error happen")            return total, err        }        total += n        file2.Write(bs[:n])    }    return total, nil}func copyFile2(srcFile, destFile string) (int64, error) {    file1, err := os.Open(srcFile) //这里读 所以用open就足够了    if err != nil {        return 0, err    }    file2, err := os.OpenFile(destFile, os.O_WRONLY|os.O_CREATE, os.ModePerm) //这里要写文件 所以须要用到OpenFile    if err != nil {        return 0, err    }    // 敞开文件    defer file1.Close()    defer file2.Close()    //就是在这里间接调用库函数~    return io.Copy(file2, file1)}

ioutil包的办法实现

然而因为ioutil包中的writeFile和readFile办法都是一次性读取再一次性写入,对大文件并不敌对,这里不再开展。

参考资料起源:bilibili