gpt4 book ai didi

file - 复制文件的简单方法

转载 作者:IT老高 更新时间:2023-10-28 12:57:59 25 4
gpt4 key购买 nike

有什么简单/快速的方法可以在 Go 中复制文件吗?

我在 Doc 中找不到快速方法,搜索互联网也无济于事。

最佳答案

Warning: This answer is mainly about adding a hard link to a file, not about copying the contents.

健壮高效副本在概念上很简单,但由于需要处理许多边缘情况和系统限制,因此实现起来并不简单。目标操作系统及其配置。

如果您只是想复制现有文件,您可以使用 os.Link(srcName, dstName)。这避免了在应用程序中移动字节并节省磁盘空间。对于大文件,这可以节省大量时间和空间。

但是不同的操作系统对硬链接(hard link)的工作方式有不同的限制。根据您的应用程序和目标系统配置,Link() 调用可能并非在所有情况下都有效。

如果您想要一个通用、健壮且高效的复制函数,请将 Copy() 更新为:

  1. 执行检查以确保至少某种形式的复制会成功(访问权限、目录存在等)
  2. 检查两个文件是否已经存在并且相同os.SameFile,如果相同则返回成功
  3. 尝试链接,成功则返回
  4. 复制字节(所有有效均失败),返回结果

一种优化是在 go 例程中复制字节,这样调用者就不会阻塞字节复制。这样做会增加调用者正确处理成功/错误情况的复杂性。

如果我想要两者,我将有两个不同的复制函数: CopyFile(src, dst string) (error) 用于阻塞复制和 CopyFileAsync(src, dst string) (chan c, error) 将一个信令 channel 传回给异步情况的调用者。

package main

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

// CopyFile copies a file from src to dst. If src and dst files exist, and are
// the same, then return success. Otherise, attempt to create a hard link
// between the two files. If that fail, copy the file contents from src to dst.
func CopyFile(src, dst string) (err error) {
sfi, err := os.Stat(src)
if err != nil {
return
}
if !sfi.Mode().IsRegular() {
// cannot copy non-regular files (e.g., directories,
// symlinks, devices, etc.)
return fmt.Errorf("CopyFile: non-regular source file %s (%q)", sfi.Name(), sfi.Mode().String())
}
dfi, err := os.Stat(dst)
if err != nil {
if !os.IsNotExist(err) {
return
}
} else {
if !(dfi.Mode().IsRegular()) {
return fmt.Errorf("CopyFile: non-regular destination file %s (%q)", dfi.Name(), dfi.Mode().String())
}
if os.SameFile(sfi, dfi) {
return
}
}
if err = os.Link(src, dst); err == nil {
return
}
err = copyFileContents(src, dst)
return
}

// copyFileContents copies the contents of the file named src to the file named
// by dst. The file will be created if it does not already exist. If the
// destination file exists, all it's contents will be replaced by the contents
// of the source file.
func copyFileContents(src, dst string) (err error) {
in, err := os.Open(src)
if err != nil {
return
}
defer in.Close()
out, err := os.Create(dst)
if err != nil {
return
}
defer func() {
cerr := out.Close()
if err == nil {
err = cerr
}
}()
if _, err = io.Copy(out, in); err != nil {
return
}
err = out.Sync()
return
}

func main() {
fmt.Printf("Copying %s to %s\n", os.Args[1], os.Args[2])
err := CopyFile(os.Args[1], os.Args[2])
if err != nil {
fmt.Printf("CopyFile failed %q\n", err)
} else {
fmt.Printf("CopyFile succeeded\n")
}
}

关于file - 复制文件的简单方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21060945/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com