英文:
How do you copy a file in Go?
问题
我有以下函数用于将文件(实际上是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)
}
}
我找到的最接近的问题是这个问题,它有一个被接受的答案,建议使用硬链接/软链接,并且如果文件已经存在,不会中止。
英文:
I have the following function to copy a file (io.Reader actually) to the destination string location. However, it seems only part of the file is actually copied resulting in a corrupt file. What am I doing wrong?
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
}
I'm using this with the filepath.Walk(dir, visit)
method to process files in a directory.
// 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)
}
}
The current closest question I could has an accepted answer that recommends using hard/soft links and doesn't abort if the file already exists.
答案1
得分: 14
以下是翻译好的代码:
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") // 如果文件不存在则创建
check(err)
defer destFile.Close()
_, err = io.Copy(destFile, srcFile) // 检查第一个返回值以获取复制的字节数
check(err)
err = destFile.Sync()
check(err)
}
func check(err error) {
if err != nil {
fmt.Println("错误:", err.Error())
os.Exit(1)
}
}
这段代码对我来说是可行的。请使用io.Copy
的返回值来检查复制的字节数。
英文:
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)
}
}
This code works for me. Do check the number of bytes copied with the return value from io.Copy
.
答案2
得分: 0
另一个选项是使用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
英文:
Another option is 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)
}
}
答案3
得分: -2
最简单的复制 Golang 的方法是 - http://golang.org/pkg/io/#Copy
英文:
Easiest way to do a copy golang is - http://golang.org/pkg/io/#Copy
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论