汇总文件的相关操作

embiid · · 782 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

**我们在进行文件的相关操作时,往往不明白在哪种情况下使用那些函数,每次查百度导致开发效率低下,我这里列举一些方便以后查询:** * **读取整个文件** * **从文件的某个位置开始,进行读、写n个字符操作** * **拷贝文件到另一个文件,或拷贝文件的前面n个字符到另一个文件** * **将多个文件汇聚到一个文件来进行操作** * **将多个字符同时写到多个文件中** * **获取文件的相关信息(名称、大小、是否为文件夹、文件权限、创建、最后访问、最后修改时间、绝对路径、重命名操作、是否存在)** * **获取文件夹的所有文件** * **将一个文件的内容写入到另一个文件中,可控制写入内容** **1、读取整个文件** ```go func test1() { f, err := os.Open("d:/a.txt") if err != nil { panic(err) } defer f.Close() // 读取整个文件 1. 使用stat获取文件长度,再开辟空间,将数据写到变量中,输出到终端 fi, err := f.Stat() if err != nil { panic(err) } b := make([]byte, fi.Size()) if _, err = f.Read(b); err != nil { panic(err) } os.Stdout.Write(b) // 读取整个文件 2. 直接使用ioutil的ReadAll函数 b, err = ioutil.ReadAll(f) if err != nil { panic(err) } os.Stdout.Write(b) } ``` **2、从文件的某个位置开始,进行读、写n个字符操作** ```go func test2() { f, err := os.OpenFile("d:/a.txt", os.O_RDWR, 0755) if err != nil { panic(err) } defer f.Close() // 设置操作文件的当前位置为倒数第10个字符 if _, err := f.Seek(-10, io.SeekEnd); err != nil { panic(err) } // 从当前位置读取5个字符 b := make([]byte, 10) if _, err := f.ReadAt(b, 5); err != nil { panic(err) } os.Stdout.Write(b) // 从当前位置写5个字符(相当于覆盖文件的最后5个字符) f.WriteAt(b, 5) } ``` **3、拷贝文件到另一个文件,或拷贝文件的前面n个字符到另一个文件** ```go func test3() { f1, err := os.Open("d:/a.txt") if err != nil { panic(err) } defer f1.Close() f2, err := os.OpenFile("d:/b.txt", os.O_CREATE | os.O_RDWR, 0755) if err != nil { panic(err) } defer f2.Close() // 拷贝f1的所有字符到f2的前面,如果f2的size比f1大,那么后面的字符依然保留 // 如果要在f2进行追加,使用os.O_APPEND if _, err := io.Copy(f2, f1); err != nil { panic(err) } // 拷贝f1的n个字符到f2的前面 if _, err := io.CopyN(f2, f1, 10); err != nil { panic(err) } } ``` **4、 将多个文件汇聚到一个文件来进行操作** ```go func test4() { f1, err := os.Open("d:/a.txt") if err != nil { panic(err) } defer f1.Close() f2, err := os.Open("d:/b.txt") if err != nil { panic(err) } defer f2.Close() // 将2个file.Reade合并成一个Reader r := io.MultiReader(f1, f2) // 轮询读取reader中的数据 buf := make([]byte, 10) data := make([]byte, 0, 128) for n, err := r.Read(buf); err != io.EOF; n, err = r.Read(buf) { if err != nil { panic(err) } data = append(data, buf[:n]...) } os.Stdout.Write(data) } ``` **5、将多个字符同时写到多个文件中** ```go func test5() { f, err := os.OpenFile("d:/a.txt", os.O_CREATE | os.O_RDWR | os.O_APPEND, 0755) if err != nil { panic(err) } defer f.Close() // 将file和标准输出合并到一个writer中 w := io.MultiWriter(f, os.Stdout) // 每次write都会写到w包含的所有writer中 w.Write([]byte("helloworld")) w.Write([]byte("nihaoshijie")) } ``` **6、获取文件的相关信息(名称、大小、是否为文件夹、文件权限、创建、最后访问、最后修改时间、绝对路径、重命名操作、是否存在)** ```go func test6() { f, err := os.OpenFile("d:/a.txt", os.O_CREATE|os.O_RDWR, 0755) if err != nil { panic(err) } defer f.Close() fi, err := f.Stat() if err != nil { panic(err) } // 名称、大小、是否为文件夹、详细信息、文件权限、最后修改时间 fmt.Printf("name: %s\n", fi.Name()) fmt.Printf("size: %d\n", fi.Size()) fmt.Printf("isDir: %t\n", fi.IsDir()) fmt.Printf("sys: %v\n", fi.Sys()) fmt.Printf("mode: %o\n", fi.Mode()) fmt.Printf("modTime: %s\n", fi.ModTime()) // 获取详细信息中的文件创建时间,具体详细信息见Stat_t结构体(windows和linux不同) // windows // CreatetionTime uint32 // LastAccessTime uint32 if reflect.ValueOf(fi.Sys()).Elem().FieldByName("CreatetionTime").IsValid() { ctim := reflect.ValueOf(fi.Sys()).Elem().FieldByName("CreatetionTime").Field(0).Uint() fmt.Printf("ctim: %d\n", ctim) } // 获取文件的绝对路径 dir, err := filepath.Abs("d:/a.txt") if err != nil { panic(err) } fmt.Printf("dir: %s\n", dir) // 判断文件是否不存在 if _, err := os.Stat("d:/c.txt"); err != nil { if os.IsNotExist(err) { fmt.Println("file not exist") } else { panic(err) } } // 重命名文件或文件夹(要有权限/文件已关闭) if err := os.Rename("d:/b.txt", "d:/d.txt"); err != nil { panic(err) } } ``` **7、获取文件夹的所有文件** ```go func test7() { files, err := ioutil.ReadDir("d:/") if err != nil { panic(err) } // 获取文件夹下所有文件和文件夹的相关信息 for _, f := range files { fmt.Printf("name: %s, size: %d, isDir: %t\n", f.Name(), f.Size(), f.IsDir()) } } ``` **8、将一个文件的内容写入到另一个文件中,可控制写入内容** ```go func test8() { f1, err := os.Open("d:/a.txt") if err != nil { panic(err) } defer f1.Close() f2, err := os.OpenFile("d:/b.txt", os.O_CREATE | os.O_RDWR | os.O_APPEND, 0755) if err != nil { panic(err) } defer f2.Close() // 设置将从f1中读到的写到f2中 r := io.TeeReader(f1, f2) // 循环5次读取f1前面100个字符,每次读取后会自动写到f2中 for i := 0; i < 5; i++ { f1.Seek(0, io.SeekStart) if _, err := r.Read(make([]byte, 100)); err != nil { if err == io.EOF{ return } panic(err) } time.Sleep(time.Second) } } ``` 案例来源于: 《go语言标准库》 https://books.studygolang.com/The-Golang-Standard-Library-by-Example/chapter01/01.1.html

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

782 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传