【发布时间】: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.OpenFile和os.O_EXCL并使用os.IsExist测试错误以安全地检测现有文件。