美文网首页golang
19-文件操作

19-文件操作

作者: 极客江南 | 来源:发表于2018-09-28 16:06 被阅读271次

    文件的打开和关闭

    • 和C语言一样, Go语言中操作文件也是通过一个FILE结构体
    type file struct {
        pfd     poll.FD
        name    string
        dirinfo *dirInfo 
    }
    type File struct {
        *file // os specific
    }
    
    • Open函数
      • func Open(name string) (file *File, err error)
      • Open打开一个文件用于读取
    • Close函数
      • func (f *File) Close() error
      • Close关闭文件f
    package main
    import (
        "fmt"
        "os"
    )
    
    func main() {
        // 1.打开一个文件
        // 注意: 文件不存在不会创建, 会报错
        // 注意: 通过Open打开只能读取, 不能写入
        fp, err := os.Open("d:/lnj.txt")
        if err != nil{
            fmt.Println(err)
        }else{
            fmt.Println(fp)
        }
    
        // 2.关闭一个文件
        defer func() {
            err = fp.Close()
            if err != nil {
                fmt.Println(err)
            }
        }()
    }
    

    文件读取

    • Read函数(不带缓冲区去读)
      • func (f *File) Read(b []byte) (n int, err error)
      • Read方法从f中读取最多len(b)字节数据并写入b,
    package main
    
    import (
        "fmt"
        "io"
        "os"
    )
    
    func main() {
        // 1.打开一个文件
        // 注意: 文件不存在不会创建, 会报错
        // 注意: 通过Open打开只能读取, 不能写入
        fp, err := os.Open("d:/lnj.txt")
        if err != nil{
            fmt.Println(err)
        }else{
            fmt.Println(fp)
        }
    
        // 2.关闭一个文件
        defer func() {
            err = fp.Close()
            if err != nil {
                fmt.Println(err)
            }
        }()
    
        // 3.读取指定指定字节个数据
        // 注意点: \n也会被读取进来
        //buf := make([]byte, 50)
        //count, err := fp.Read(buf)
        //if err != nil {
        //  fmt.Println(err)
        //}else{
        //  fmt.Println(count)
        //  fmt.Println(string(buf))
        //}
    
        // 4.读取文件中所有内容, 直到文件末尾为止
        buf := make([]byte, 10)
        for{
            count, err := fp.Read(buf)
            // 注意: 这行代码要放到判断EOF之前, 否则会出现少读一行情况
            fmt.Print(string(buf[:count]))
            if err == io.EOF {
                break
            }
        }
    }
    
    • ReadBytes和ReadString函数(带缓冲区去读)
      • func (b *Reader) ReadBytes(delim byte) (line []byte, err error)
      • ReadBytes读取直到第一次遇到delim字节
      • func (b *Reader) ReadString(delim byte) (line string, err error)
      • ReadString读取直到第一次遇到delim字节
    package main
    
    import (
        "bufio"
        "fmt"
        "io"
        "os"
    )
    
    func main() {
        // 1.打开一个文件
        // 注意: 文件不存在不会创建, 会报错
        // 注意: 通过Open打开只能读取, 不能写入
        fp, err := os.Open("d:/lnj.txt")
        if err != nil{
            fmt.Println(err)
        }else{
            fmt.Println(fp)
        }
    
        // 2.关闭一个文件
        defer func() {
            err = fp.Close()
            if err != nil {
                fmt.Println(err)
            }
        }()
    
        // 3.读取一行数据
        // 创建读取缓冲区, 默认大小4096
        //r :=bufio.NewReader(fp)
        //buf, err := r.ReadBytes('\n')
        //buf, err := r.ReadString('\n')
        //if err != nil{
        //  fmt.Println(err)
        //}else{
        //  fmt.Println(string(buf))
        //}
    
        // 4.读取文件中所有内容, 直到文件末尾为止
        r :=bufio.NewReader(fp)
        for{
            //buf, err := r.ReadBytes('\n')
            buf, err := r.ReadString('\n')
            fmt.Print(string(buf))
            if err == io.EOF{
                break
            }
        }
    }
    
    • ReadFile函数
      • func ReadFile(filename string) ([]byte, error)
      • 从filename指定的文件中读取数据并返回文件的所有内容
      • 不适合大文件读取
    package main
    
    import (
        "fmt"
        "io/ioutil"
    )
    
    func main() {
    
        filePath := "d:/lnj.txt"
        buf, err := ioutil.ReadFile(filePath)
        if err !=nil {
            fmt.Println(err)
        }else{
            fmt.Println(string(buf))
        }
    }
    

    文件创建和写入

    • Create函数
      • func Create(name string) (file *File, err error)
      • Create采用模式0666(任何人都可读写,不可执行)创建一个名为name的文件
      • 如果文件存在会覆盖原有文件
    • Write函数
      • func (f *File) Write(b []byte) (n int, err error)
      • 将指定字节数组写入到文件中
    • WriteString函数
      • func (f *File) WriteString(s string) (ret int, err error)
      • 将指定字符串写入到文件中
    package main
    
    import (
        "fmt"
        "os"
    )
    
    func main() {
    
        // 1.创建一个文件
        fp, err := os.Create("d:/lnj.txt")
        if err != nil{
            fmt.Println(err)
        }
        // 2.关闭打开的文件
        defer func() {
            err := fp.Close()
            if err != nil {
                fmt.Println(err)
            }
        }()
        // 2.往文件中写入数据
        // 注意: Windows换行是\r\n
        bytes := []byte{'l','n','j','\r','\n'}
        fp.Write(bytes)
        
        fp.WriteString("www.it666.com\r\n")
        fp.WriteString("www.itzb.com\r\n")
        // 注意: Go语言采用UTF-8编码, 一个中文占用3个字节
        fp.WriteString("李南江")
    }
    
    • OpenFile函数
      • func OpenFile(name string, flag int, perm FileMode) (file *File, err error)
      • 第一个参数: 打开的路径
      • 第二个参数: 打开的模式
      const (
        O_RDONLY int = syscall.O_RDONLY // 只读模式打开文件
        O_WRONLY int = syscall.O_WRONLY // 只写模式打开文件
        O_RDWR   int = syscall.O_RDWR   // 读写模式打开文件
        O_APPEND int = syscall.O_APPEND // 写操作时将数据附加到文件尾部
        O_CREATE int = syscall.O_CREAT  // 如果不存在将创建一个新文件
        O_EXCL   int = syscall.O_EXCL   // 和O_CREATE配合使用,文件必须不存在
        O_SYNC   int = syscall.O_SYNC   // 打开文件用于同步I/O
        O_TRUNC  int = syscall.O_TRUNC  // 如果可能,打开时清空文件
      )
      
      • 第三个参数: 指定权限
        • 0没有任何权限
        • 1.执行权限(如果是可执行程序, 可以运行)
        • 2.写权限
        • 3.写权限和执行权限
        • 4.读权限
        • 5.读权限和执行权限
        • 6.读权限和写权限
        • 7.读权限和写权限以及执行权限
      const (
        // 单字符是被String方法用于格式化的属性缩写。
        ModeDir        FileMode = 1 << (32 - 1 - iota) // d: 目录
        ModeAppend                                     // a: 只能写入,且只能写入到末尾
        ModeExclusive                                  // l: 用于执行
        ModeTemporary                                  // T: 临时文件(非备份文件)
        ModeSymlink                                    // L: 符号链接(不是快捷方式文件)
        ModeDevice                                     // D: 设备
        ModeNamedPipe                                  // p: 命名管道(FIFO)
        ModeSocket                                     // S: Unix域socket
        ModeSetuid                                     // u: 表示文件具有其创建者用户id权限
        ModeSetgid                                     // g: 表示文件具有其创建者组id的权限
        ModeCharDevice                                 // c: 字符设备,需已设置ModeDevice
        ModeSticky                                     // t: 只有root/创建者能删除/移动文件
        // 覆盖所有类型位(用于通过&获取类型位),对普通文件,所有这些位都不应被设置
        ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice
        ModePerm FileMode = 0777 // 覆盖所有Unix权限位(用于通过&获取类型位)
      )
      
    • 不带缓冲区写入
    package main
    
    import (
        "fmt"
        "os"
    )
    
    func main() {
    
        // 注意点: 第三个参数在Windows没有效果
        // -rw-rw-rw- (666)   所有用户都有文件读、写权限。
        //-rwxrwxrwx (777)  所有用户都有读、写、执行权限。
        // 1.打开文件
        //fp, err := os.OpenFile("d:/lnj.txt", os.O_CREATE|os.O_RDWR, 0666)
        fp, err := os.OpenFile("d:/lnj.txt", os.O_CREATE|os.O_APPEND, 0666)
        if err != nil {
            fmt.Println(err)
        }
        // 2.关闭打开的文件
        defer func() {
            err := fp.Close()
            if err != nil {
                fmt.Println(err)
            }
        }()
    
        // 注意点:
        // 如果O_RDWR模式打开, 被打开文件已经有内容, 会从最前面开始覆盖
        // 如果O_APPEND模式打开, 被打开文件已经有内容, 会从在最后追加
        // 3.往文件中写入数据
        bytes := []byte{'l','n','j','\r','\n'}
        fp.Write(bytes)
        fp.WriteString("www.it666.com\r\n")
    }
    
    • 带缓冲区写入
    package main
    
    import (
        "bufio"
        "fmt"
        "os"
    )
    
    func main() {
    
        // 1.打开文件
        fp, err := os.OpenFile("d:/lnj.txt", os.O_CREATE|os.O_APPEND, 0666)
        if err != nil {
            fmt.Println(err)
        }
        // 2.关闭打开的文件
        defer func() {
            err := fp.Close()
            if err != nil {
                fmt.Println(err)
            }
        }()
    
        // 3.创建缓冲区
        w := bufio.NewWriter(fp)
    
        // 4.写入数据到缓冲区
        bytes := []byte{'l','n','j','\r','\n'}
        w.Write(bytes)
        w.WriteString("www.it666.com\r\n")
    
        // 5.将缓冲区中的数据刷新到文件
        w.Flush()
    }
    
    • WriteFile函数
    package main
    
    import (
        "fmt"
        "io/ioutil"
    )
    
    func main() {
    
        // 1.写入数据到指定文件
        data := []byte{'l','n','j','\r','\n'}
        err := ioutil.WriteFile("d:/abc.txt", data, 0666)
        if err != nil {
            fmt.Println(err)
        }else{
            fmt.Println("写入成功")
        }
    }
    

    判断文件是否存在

    • Stat函数
      • func Stat(name string) (fi FileInfo, err error)
    • 返回值: FileInfo
    type FileInfo interface {
        Name() string       // 文件的名字(不含扩展名)
        Size() int64        // 普通文件返回值表示其大小;其他文件的返回值含义各系统不同
        Mode() FileMode     // 文件的模式位
        ModTime() time.Time // 文件的修改时间
        IsDir() bool        // 等价于Mode().IsDir()
        Sys() interface{}   // 底层数据来源(可以返回nil)
    }
    
    • 返回值: error
      • 返回值error等于nil,代表文件存在
      • 返回值error不等于nil, 可以进一步通过IsNotExist判断, 如果返回true代表文件不存在
      • 返回值error如果返回其它错误, 则不确定文件是否存在
    package main
    
    import (
        "fmt"
        "os"
    )
    
    func main() {
    
        info, err := os.Stat("d:/lnj.txt")
        if err == nil {
            fmt.Println("文件存在")
            fmt.Println(info.Name())
        }else if os.IsNotExist(err) {
            fmt.Println("文件不存在")
        }else{
            fmt.Println("不确定")
        }
    }
    

    练习

    • 将一个文本文件拷贝到另外一个文件中
      • 尝试用上面学习的其它方法实现下
    package main
    
    import (
        "fmt"
        "io/ioutil"
    )
    
    func main() {
    
        // 1.读取一个文件
        buf, err := ioutil.ReadFile("d:/lnj.txt")
        if err != nil {
            fmt.Println(err)
            return
        }
        // 2.写入读取的数据到另一个文件
        err =ioutil.WriteFile("d:/abc.txt", buf, 0666)
        if err != nil {
            fmt.Println(err)
            return
        }
        fmt.Println("拷贝完成")
    
    }
    
    • 将一个图片/视频文件拷贝到另一个文件
    package main
    
    import (
        "bufio"
        "fmt"
        "io"
        "os"
    )
    
    func main() {
    
        // 1.定义拷贝文件的路径
        scrPath := "D:/a.png"
        destPath := "E:/b.png"
        // 2.打开被拷贝文件
        fr, err := os.Open(scrPath)
        if err != nil {
            fmt.Println(err)
            return
        }
        // 3.关闭打开文件
        defer func() {
            err := fr.Close()
            if err != nil{
                fmt.Println(err)
            }
        }()
        // 4.创建读取缓冲区
        r := bufio.NewReader(fr)
    
        // 1.创建写入文件
        fw, err := os.Create(destPath)
        if err != nil {
            fmt.Println(err)
            return
        }
        // 2.关闭打开文件
        defer func() {
            err := fw.Close()
            if err != nil{
                fmt.Println(err)
            }
        }()
        // 3.创建写入缓冲区
        w := bufio.NewWriter(fw)
        // 4.利用系统copy函数完成拷贝
        count, err := io.Copy(w, r)
        if err != nil {
            fmt.Println(err)
            return
        }
        fmt.Println(count)
        fmt.Println("拷贝完成")
    }
    
    • 自己查文档实现遍历文件夹
      • 例如: 给一个文件夹路径, 获取该文件夹下所有文件, 并将所有文件路径保存到切片中

    相关文章

      网友评论

        本文标题:19-文件操作

        本文链接:https://www.haomeiwen.com/subject/hwaeoftx.html