一个简单的目录复制程序
2014-11-02 16:15
246 查看
创建一个独立的 goroutine 遍历文件,主进程负责写入数据。程序会复制空目录,也可以设置只复制以 ".xx" 结尾的文件。
严格来说这不是复制文件,而是写入新文件。因为这个程序是创建新文件,然后写入复制数据的。我们一般的 copy 命令是不会修改文件的 ctime(change time) 状态的。
严格来说这不是复制文件,而是写入新文件。因为这个程序是创建新文件,然后写入复制数据的。我们一般的 copy 命令是不会修改文件的 ctime(change time) 状态的。
代码:
// 一个简单的目录复制程序:一个独立的 goroutine 遍历目录,主进程负责将数据写入新目录。 // 2014-11-02 Bing.L package main import ( "io" "log" "os" "path/filepath" "strings" ) type FileInfo struct { RelPath string Size int64 IsDir bool Handle *os.File } //复制文件数据 func ioCopy(srcHandle *os.File, dstPth string) (err error) { dstHandle, err := os.OpenFile(dstPth, os.O_CREATE|os.O_WRONLY, os.ModePerm) if err != nil { return err } defer srcHandle.Close() defer dstHandle.Close() _, err = io.Copy(dstHandle, srcHandle) return err } //遍历目录,将文件信息传入通道 func WalkFiles(srcDir, suffix string, c chan<- *FileInfo) { suffix = strings.ToUpper(suffix) filepath.Walk(srcDir, func(f string, fi os.FileInfo, err error) error { //遍历目录 if err != nil { log.Println("[E]", err) } fileInfo := &FileInfo{} if strings.HasSuffix(strings.ToUpper(fi.Name()), suffix) { //匹配文件 if fh, err := os.OpenFile(f, os.O_RDONLY, os.ModePerm); err != nil { log.Println("[E]", err) } else { fileInfo.Handle = fh fileInfo.RelPath, _ = filepath.Rel(srcDir, f) //相对路径 fileInfo.Size = fi.Size() fileInfo.IsDir = fi.IsDir() } c <- fileInfo } }) close(c) //遍历完成,关闭通道 } //写目标文件 func WriteFiles(dstDir string, c <-chan *FileInfo) { if err := os.Chdir(dstDir); err != nil { //切换工作路径 log.Fatalln("[F]", err) } for f := range c { if fi, err := os.Stat(f.RelPath); os.IsNotExist(err) { //目标不存在 if f.IsDir { if err := os.MkdirAll(f.RelPath, os.ModeDir); err != nil { log.Println("[E]", err) } } else { if err := ioCopy(f.Handle, f.RelPath); err != nil { log.Println("[E]", err) } else { log.Println("[I] CP:", f.RelPath) } } } else if !f.IsDir { //目标存在,而且源不是一个目录 if fi.IsDir() != f.IsDir { //检查文件名被目录名占用冲突 log.Println("[E]", "filename conflict:", f.RelPath) } else if fi.Size() != f.Size { //源和目标的大小不一致时才重写 if err := ioCopy(f.Handle, f.RelPath); err != nil { log.Println("[E]", err) } else { log.Println("[I] CP:", f.RelPath) } } } } } func main() { files_ch := make(chan *FileInfo, 100) go WalkFiles("E:\\study", ".doc", files_ch) //在一个独立的 goroutine 中遍历文件 WriteFiles("E:\\study.bak", files_ch) }
相关文章推荐
- FileOutputStream 类 和 FileInputStream类的简单介绍,附代码演示。以及一个复制媒体文件的小程序。
- 黑马程序员 编写一个程序,将d:\java目录下的所有.java文件复制到d:\jad目录下,并将原来文件的扩展名从.java改为.jad。
- FileOutputStream 类 和 FileInputStream类的简单介绍,附代码演示。以及一个复制媒体文件的小程序
- 面试题 编写一个程序,将e:\project\java目录下的所有.java文件复制到 e:\project\jad目录下,并将原来文件的扩展名从.java改为.jad。
- 编写一个程序,将djava目录下的所有.java文件复制到djad目录下,并将原来文件的扩展名从.java改为.jad
- 一个简单的文件目录打印程序
- 怎样用java写一个简单的文件复制程序
- 一个简单的扫描目录的程序
- 编写一个程序,将d:\java目录下的所有.java文件复制到d:\jad目录下,并将原来文件的扩展名从.java改为. jad
- 编写一个程序,将 d:\java 目录下的所有.java 文件复制到 d:\jad 目录下,并将原来文件的扩展名从.java 改为.jad。
- 编写一个程序,将e:\java目录下的所有.java文件复制到e:\jad目录下
- 一个简单的递归求目录的程序遇到的问题
- 编写一个程序,将d:\yy目录下的所有.java文件复制到d:\jad目录下,并将原来文件的扩展名从.java改为.txt
- 编写一个程序,将 d:\java目录下的所有.java 文件复制到d:\jad目录下,并将原来文件的扩展名从.java 改为.jad。
- 编写一个程序,将 d: \ java 目录下的所有.java 文件复制到d: \ jad 目录下,并 将原来文件的扩展名从.java 改为.jad
- 编写一个程序,将d:\java目录下的所有.java文件复制到d:\jad目录下,并将原来文件的扩展名从.java改为.jad
- 笔记1-1: 实现一个简单的ls列出目录中的所有项目的程序
- 编写一个程序,将d:\java目录下的所有.java文件复制到d:\jad目录下,并将原来文件的扩展名从.java改为.jad。
- 简单API练手:(1)复制自身程序到windows目录和系统目录下;(2)获得系统的相关信息。
- 一个简单的统计文件夹下文件或目录的程序