Go语言如何写一个文件拷贝工具_Golang文件处理项目实战

9次阅读

io.copy 是高效可靠的文件拷贝方案,默认32KB缓冲;需检查源文件存在性、显式关闭目标文件;支持进度条(io.MultiWriter)、断点续传(Seek+CopyN)及windows符号链接与权限处理。

Go语言如何写一个文件拷贝工具_Golang文件处理项目实战

io.Copy 实现基础文件拷贝,别自己循环读写

go 标准库io.Copy 已经高效处理了缓冲、边界和错误传播,直接调用比手动 Read/Write 更可靠。它默认使用 32KB 缓冲区(io.DefaultBufSize),对大多数场景足够快。

  • 源文件必须以 os.O_RDONLY 打开,目标文件建议用 os.O_CREATE | os.O_WRONLY | os.O_TRUNC
  • 记得在拷贝前检查源文件是否存在且可读:os.Stat(src),避免 io.Copy 返回模糊的 "invalid argument"
  • 拷贝完成后,显式调用 dst.Close() —— 否则可能丢失最后部分数据(尤其小文件或非阻塞写场景)

处理大文件时加进度条,用 io.MultiWriter 和自定义 Write

进度条不是靠轮询文件大小,而是拦截每次 Write 调用。把目标 *os.File 包一层,同时写入磁盘和计数器,再用 io.MultiWriter 组合多个写入目标(比如日志 + 进度回调)。

  • 不要用 os.Getwd() 拼接路径,改用 filepath.Join 处理跨平台路径分隔符
  • 进度更新频率太高会拖慢拷贝速度,建议每 1MB 或每 100 次 Write 触发一次回调
  • 注意:如果目标路径已存在且是目录,os.OpenFile 会返回 "is a Directory" 错误,需提前 os.Stat 判断类型

支持断点续传?得用 os.OpenFile 配合 Seekio.CopyN

断点续传本质是跳过已写入部分,从指定偏移继续写。这要求目标文件以 os.O_appEND 以外的方式打开(否则 Seek 无效),并手动控制读写位置。

  • 先用 dst.Seek(0, io.SeekEnd) 获取当前长度,作为起始偏移
  • 源文件也需从该偏移开始读:src.Seek(offset, io.SeekStart);注意检查 src 是否支持 Seeker 接口(如管道不支持)
  • io.CopyN(dst, src, remaining) 替代 io.Copy,避免多写
  • 续传前务必校验已写内容的哈希(如 sha256.Sum256 前 N 字节),否则网络中断+重试可能导致文件错位

windows 下复制失败常见于权限和符号链接,os.Readlinksyscall 得备着

Windows 对硬链接、符号链接、只读属性、ACL 权限更敏感。单纯 io.Copy 只能复制内容,无法保留元数据或处理链接目标。

立即学习go语言免费学习笔记(深入)”;

  • 判断是否为符号链接:os.Readlink(path),若不报错说明是符号链接,应复制链接本身而非目标
  • 设置只读属性需用 syscall.SetFileAttributes(Windows)或 os.Chmodunix),不能只依赖 os.CopyFile(Go 1.19+ 才有,且不跨平台保留属性)
  • 遇到 "access is denied" 错误,大概率是目标文件被其他进程占用(如编辑器锁住),需提示用户关闭相关程序

真正难的不是拷贝字节,而是判断“这个路径到底想表达什么”——是链接、是挂载点、是加密文件、还是 NTFS 压缩流。每种情况都得单独探测和分支处理。

text=ZqhQzanResources