【问题标题】:How do you copy a file in Go?你如何在 Go 中复制文件?
【发布时间】:2015-05-21 14:37:02
【问题描述】:

我有以下函数可以将文件(实际上是 io.Reader)复制到目标字符串位置。但是,似乎实际上只复制了文件的一部分,从而导致文件损坏。我做错了什么?

func CopyFile(in io.Reader, dst string) (err error) {

    // Does file already exist? Skip
    if _, err := os.Stat(dst); err == nil {
        return nil
    }

    err = nil

    out, err := os.Create(dst)
    if err != nil {
        fmt.Println("Error creating file", err)
        return
    }

    defer func() {
        cerr := out.Close()
        if err == nil {
            err = cerr
        }
    }()


    var bytes int64
    if bytes, err = io.Copy(out, in); err != nil {
        fmt.Println("io.Copy error")
        return
    }
    fmt.Println(bytes)

    err = out.Sync()
    return
}

我将它与filepath.Walk(dir, visit) 方法一起使用来处理目录中的文件。

// Process each matching file on our walk down the filesystem
func visit(path string, f os.FileInfo, err error) error {

    if reader, err := os.Open(path); err == nil {
        defer reader.Close()

        // http://golang.org/pkg/os/#FileInfo
        statinfo, err := reader.Stat()

        if err != nil {
            fmt.Println(err)
            return nil
        }

        fmt.Println()
        fmt.Println(statinfo.Size())

        // Directory exists and is writable
        err = CopyFile(reader, "/tmp/foo/"+f.Name())

        if err != nil {
            fmt.Println(err)
        }

    } else {
        fmt.Println("Impossible to open the file:", err)
    }
}

当前的closest question 我可以有一个可接受的答案,建议使用硬/软链接,并且如果文件已经存在则不会中止。

【问题讨论】:

  • io.Copy 返回写入的字节数。你应该检查一下,也许它会有所帮助。
  • 另外,您的代码也适用于我。你能展示一下你是如何使用这个函数的吗?
  • 你向in提供什么?您是否看到 any 错误?坏文件是否已经存在(在这种情况下您会静默返回)?
  • 顺便说一句,您的os.Stat 检查存在性,然后是os.Create(这将截断现有文件)是一场竞赛;您最终可能会截断和覆盖最近/同时创建的文件。最好使用os.OpenFileos.O_EXCL 并使用os.IsExist 测试错误以安全地检测现有文件。

标签: file go copy


【解决方案1】:
package main

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

func main() {
    srcFile, err := os.Open("test.txt")
    check(err)
    defer srcFile.Close()

    destFile, err := os.Create("test_copy.txt") // creates if file doesn't exist
    check(err)
    defer destFile.Close()

    _, err = io.Copy(destFile, srcFile) // check first var for number of bytes copied
    check(err)

    err = destFile.Sync()
    check(err)
}

func check(err error) {
    if err != nil {
        fmt.Println("Error : %s", err.Error())
        os.Exit(1)
    }
}

此代码对我有用。请检查使用来自io.Copy 的返回值复制的字节数。

【讨论】:

  • 要明确一点:在使用 defer 之前,应该始终检查 err。
  • 对。进行了更改。
  • io.Copy 通过调用 destFile.ReadFrom(srcFile) 有效地实现了复制操作。如本答案所示调用 io.Copy 是一种很好的做法,因为 io.Copy 对任何源和目标都做了“正确的事情”。
【解决方案2】:

另一个选项是ReadFrom:

package main
import "os"

func copyFile(in, out string) (int64, error) {
   i, e := os.Open(in)
   if e != nil { return 0, e }
   defer i.Close()
   o, e := os.Create(out)
   if e != nil { return 0, e }
   defer o.Close()
   return o.ReadFrom(i)
}

func main() {
   _, e := copyFile("in.txt", "out.txt")
   if e != nil {
      panic(e)
   }
}

https://golang.org/pkg/os#File.ReadFrom

【讨论】:

    【解决方案3】:

    复制 golang 最简单的方法是 - http://golang.org/pkg/io/#Copy

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-10
      • 2018-09-07
      • 2016-12-10
      • 1970-01-01
      相关资源
      最近更新 更多