汇总文件的相关操作

embiid · 2018-07-31 15:23:01 · 963 次点击 · 预计阅读时间 5 分钟 · 大约8小时之前 开始浏览    
这是一个创建于 2018-07-31 15:23:01 的文章,其中的信息可能已经有所发展或是发生改变。

我们在进行文件的相关操作时,往往不明白在哪种情况下使用那些函数,每次查百度导致开发效率低下,我这里列举一些方便以后查询:

  • 读取整个文件
  • 从文件的某个位置开始,进行读、写n个字符操作
  • 拷贝文件到另一个文件,或拷贝文件的前面n个字符到另一个文件
  • 将多个文件汇聚到一个文件来进行操作
  • 将多个字符同时写到多个文件中
  • 获取文件的相关信息(名称、大小、是否为文件夹、文件权限、创建、最后访问、最后修改时间、绝对路径、重命名操作、是否存在)
  • 获取文件夹的所有文件
  • 将一个文件的内容写入到另一个文件中,可控制写入内容

1、读取整个文件

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个字符操作

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个字符到另一个文件

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、 将多个文件汇聚到一个文件来进行操作

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、将多个字符同时写到多个文件中

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、获取文件的相关信息(名称、大小、是否为文件夹、文件权限、创建、最后访问、最后修改时间、绝对路径、重命名操作、是否存在)

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、获取文件夹的所有文件

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、将一个文件的内容写入到另一个文件中,可控制写入内容

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

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