• golang 文件操作io bufio ioutil


    io

    golang中 os.File 库封装了文件相关操作,File是一个结构体。

    go语言标准库文档:https://studygolang.com/static/pkgdoc/pkg/os.htm#File

    具体的使用:

    1、打开文件
    1)os.Open

    //Open打开一个文件用于读取。
    //如果操作成功,返回的文件对象的方法可用于读取数据;对应的文件描述符具有O_RDONLY模式。
    //如果出错,错误底层类型是*PathError。
    func Open(name string) (file *File, err error)

    1.1  os.Create 创建文件

     f,err := os.Create( fileName )
    
    defer f.Close()
    
    if err !=nil {
    
      fmt.Println( err.Error() )
    
    } else {
    
      _,err=f.Write([]byte("要写入的文本内容"))
    
      fmt.Println( err.Error() )
    
    }

    // 向文件写入字节数据 func (f *File) Write(b []byte) (n int, err error) //

    向文件写入字符串 func (f *File) WriteString(s string) (ret int, err error)

     

    2)os.OpenFile

    OpenFile是一个更一般性的文件打开函数,大多数调用者都应用Open或Create代替本函数。它会使用指定的选项(如O_RDONLY等)、指定的模式(如0666等)打开指定名称的文件。如果操作成功,返回的文件对象可用于I/O。如果出错,错误底层类型是*PathError。

    func OpenFile(name string, flag int, perm FileMode) (file *File, err error)
    ① flag参数,表示打开文件的几种模式,可用 | 符号组合使用,可用值为:

    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 // 如果可能,打开时清空文件 !!!谨慎使用!!!
    )


    ② FileMode参数代表文件的模式和权限位,主要使用在Linux和Unix系统下,windows系统下无效。

    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权限位(用于通过&获取类型位)
    )


    2、关闭文件//Close关闭文件f,使文件不能用于读写。它返回可能出现的错误。

    func (f *File) Close() error

    //打开文件
    file, err := os.Open("test.txt")
    if err != nil {
        fmt.Println("open file err=", err)
    }
    fmt.Printf("file=%v", file) //这里打印出 file=&{0xc00007a780} ,因为file是一个指针
     
    //关闭文件file,要及时关闭文件句柄file,防止内存泄漏
    defer file.Close()


    //关闭文件file,要及时关闭文件句柄file,防止内存泄漏
    defer file.Close()
    3、读取文件
    1)读取到file中,再利用ioutil将file直接读取到[]byte中

    # 例子:

    func Read1() string {
        f, err := os.Open("./test.txt")
        if err != nil {
            fmt.Println("read file fail", err)
            return ""
        }
        defer f.Close()
     
        fd, err := ioutil.ReadAll(f)
        if err != nil {
            fmt.Println("read to fd fail", err)
            return ""
        }
     
        return string(fd)
    }


    2)io/ioutil包中的ReadFile方法一次性读取,适用于文件不大的情况下。

    这种方式下文件的Open和Close被封装到ReadFile函数内部,直接读取即可。

    # 例子:

    func Read2() string {
    f, err := ioutil.ReadFile("./test.txt")
    if err != nil {
    fmt.Println("read fail", err)
    }
    return string(f)
    }
    3)使用带缓冲区的方式

    func Read3() string {
        file, err := os.Open("./basic/type/test.txt")
        if err != nil {
            fmt.Println("open file err=", err)
        }
        defer file.Close()
     
        var f string
     
        //创建一个 *Reader,带缓冲区的
        //默认缓冲区为defaultBufSize = 4096
        reader := bufio.NewReader(file)
        //循环读取文件内容
        for {
            str, err := reader.ReadString('\n')
            f += str
            if err == io.EOF { //io.EOF表示文件的末尾
                break
            }
        }
     
        return f
    }

     经验证,上面的'\n' 对windows换行和linux都适用。

     reader还有一个ReadLine的方法,不过是低阶api,上层封装是 ReadBytes('\n') or ReadString('\n').

    func (*bufio.Reader).ReadLine() (line []byte, isPrefix bool, err error)

    ReadLine is a low-level line-reading primitive. Most callers should use ReadBytes('\n') or ReadString('\n') instead or use a Scanner

    问题:为什么

    if err == io.EOF { /

    要放在后面。因为读取到最后一行(这行还有内容),这行返回的str有内容,但是err是EOF.

    ReadString("\n")应该是读到\n或EOF时返回,所以最后一行会返回EOF,但是你的代码中判断EOF后直接break了,此时line就是最后一行的内容

    4、写入文件

    func write1()  {
        filePath := "./basic/type/test1.txt"
        file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666)
        if err != nil {
            fmt.Printf("open file err = %v\n", err)
            return
        }
     
        defer file.Close()
     
        //写入文件
        str := "hello world\r\n"
        writer := bufio.NewWriter(file)
        for i := 0; i < 5; i++ {
            writer.WriteString(str)
        }
     
        //writer是带缓存的,因此在调用writerString方法时,其实内存是先写入缓存的
        //Flush方法将缓存的数据真正写入文件中
        writer.Flush()
    }

    ————————————————
    参考链接:https://blog.csdn.net/lff1123/article/details/122747038

     https://blog.csdn.net/weixin_37717557/article/details/106532544

  • 相关阅读:
    冲刺阶段个人博客9
    冲刺阶段个人博客8
    梦断代码阅读笔记02
    我关于搜狗输入法的用户体验描述
    冲刺阶段个人博客07
    冲刺阶段个人博客06
    冲刺阶段个人博客05
    冲刺阶段个人博客04
    BZOJ 2006 超级钢琴(堆+主席树)
    BZOJ 1924 所驼门王的宝藏(强连通分量缩点+DAG最长链)
  • 原文地址:https://www.cnblogs.com/youxin/p/16214575.html
Copyright © 2020-2023  润新知