本文介绍了在Golang中复制文件的简单方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Go中有没有简单/快速的方式复制档案?

Is there any simple/fast way to copy a file in Go?

我在文件中找不到快速的方式,帮助。

I couldn't find a fast way in the Doc's and searching the internet doesn't help as well.

推荐答案

强大的效率复制在概念上很简单,由于需要处理目标操作系统及其配置所带来的许多边缘情况和系统限制,因此它们很容易实现。

A robust and efficient copy is conceptually simple, but not simple to implement due to the need to handle a number of edge cases and system limitations that are imposed by the target operating system and it's configuration.

如果你只想做现有文件的副本,您可以使用 os.Link(srcName,dstName)。这避免了在应用程序中移动字节并节省磁盘空间。对于大文件,这是一个重要的时间和空间节省。

If you simply want to make a duplicate of the existing file you can use os.Link(srcName, dstName). This avoids having to move bytes around in the application and saves disk space. For large files, this is a significant time and space saving.

但是,各种操作系统有不同的限制如何硬链接工作。根据您的应用程序和目标系统配置, Link()可能无法在所有情况下工作。

But various operating systems have different restrictions on how hard links work. Depending on your application and your target system configuration, Link() calls may not work in all cases.

您需要一个单一的通用,健壮和高效的复制功能,将 Copy()更新为:

If you want a single generic, robust and efficient copy function, update Copy() to:


  1. 执行检查以确保至少某种形式的复制会成功(访问权限,目录存在等)。

  2. 检查这两个文件是否已存在且是否相同
    os.SameFile ,如果他们是相同则返回成功

  3. 尝试链接,
  4. 复制字节(所有效率均失败),返回结果

  1. Perform checks to ensure that at least some form of copy will succeed (access permissions, directories exist, etc.)
  2. Check to see if both files already exist and are the same usingos.SameFile, return success if they are the same
  3. Attempt a Link, return if success
  4. Copy the bytes (all efficient means failed), return result

在go程序中,所以调用者不会阻塞字节复制。这样做对调用者施加额外的复杂性以正确处理成功/错误情况。

An optimization would be to copy the bytes in a go routine so the caller doesn't block on the byte copy. Doing so imposes additional complexity on the caller to handle the success/error case properly.

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



If I wanted both, I would have two different copy functions: CopyFile(src, dst string) (error) for a blocking copy and CopyFileAsync(src, dst string) (chan c, error) which passes a signaling channel back to the caller for the asynchronous case.

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")
    }
}

这篇关于在Golang中复制文件的简单方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 11:46
查看更多