zoukankan      html  css  js  c++  java
  • golang学习笔记---文件操作

    go中打开文件常用os.open,需要注意的是os.open只接收一个文件名参数,默认只有只读权限,文件的读写 flag 是以常量的形式定义如下

    const (
            // Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified.
            O_RDONLY int = syscall.O_RDONLY // open the file read-only.
            O_WRONLY int = syscall.O_WRONLY // open the file write-only.
            O_RDWR   int = syscall.O_RDWR   // open the file read-write.
            // The remaining values may be or'ed in to control behavior.
            O_APPEND int = syscall.O_APPEND // append data to the file when writing.
            O_CREATE int = syscall.O_CREAT  // create a new file if none exists.
            O_EXCL   int = syscall.O_EXCL   // used with O_CREATE, file must not exist.
            O_SYNC   int = syscall.O_SYNC   // open for synchronous I/O.
            O_TRUNC  int = syscall.O_TRUNC  // truncate regular writable file when opened.
    )

    文件打开格式如

    file, err := os.Open("text.txt")

    文件读取

    os.open打开文件后付给file然后通过read的方法读取并接收一个buf []byte 的参数类型,读取到文件末尾会返回0以及 io.EOF,可以通过0或者io.EOF进行判断文件是否读取完毕。

    package main
     
    import (
        "os"
        "fmt"
    )
     
    func main()  {
        file, err := os.Open("text.txt")
        if err != nil {
            fmt.Println(err)
        }
        buf := make([]byte, 126)
        n, err := file.Read(buf)
        if err != nil {
            fmt.Println(err)
        }
        fmt.Printf("%d = %q", n, buf)
    }

    如果想在读取文件的时候加上权限可以使用os.openFile

    package main
    
    import (
        "log"
        "os"
    )
    
    func main() {
        file, err := os.OpenFile("test.txt", os.O_WRONLY, 0666)
        if err != nil {
            if os.IsPermission(err) {
                log.Println("Error: Write permission denied.")
            }
        }
        file.Close()
    
        // Test read permissions
        file, err = os.OpenFile("test.txt", os.O_RDONLY, 0666)
        if err != nil {
            if os.IsPermission(err) {
                log.Println("Error: Read permission denied.")
            }
        }
        file.Close()
    }

    注意的是在os.openFile后可根权限设置

    os.O_WRONLY 只写
    os.O_CREATE 创建文件
    os.O_RDONLY 只读
    os.O_RDWR   读写
    os.O_TRUNC  清空
    os.O_APPEND 追加

    循环读取;

    package main
    
    import (
        "fmt"
        "os"
    )
    
    func main() {
        userFile := "test.txt"
        fin, err := os.Open(userFile)
        defer fin.Close()
        if err != nil {
            fmt.Println(userFile, err)
            return
        }
        buf := make([]byte, 100)
        for {
            n, _ := fin.Read(buf)
            if 0 == n {
                break
            }
            os.Stdout.Write(buf[:n])
        }
    }

    这里os.open只是提供了简单的read读取文件方法,写文件时还需要调用上面的提到的os.oenFile方法。

    当然在go中还提供了bufil包进行文件的一次列操作。

    bufio

    bufio 顾名思义就是带 buffer 的 IO,由于频繁读写磁盘会有相当的性能开销,因为一次磁盘的读写就是一次系统的调用,所以 Go 提供了一个 buffer 来缓冲读写的数据,比如多次写磁盘 bufio 就会把数据先缓冲起来,待 buffer 装满之后一次性写入,又比如多次读数据,bufio 会预先按照 buffer 的大小(一般是磁盘 block size 的整数倍)尽量多的读取数据,也就是采用预读的技术以提高读的性能。bufio 提供了 Reader 、 Writer、 Scanner 来进行文件的读写,其中 Reader 和 Scanner 都支持按行读取文件。

    package main
    
    import (
        "bufio"
        "fmt"
        "io"
        "os"
    )
    
    // bufio按行读取示例
    func main() {
        file, err := os.Open("test.txt")
        if err != nil {
            fmt.Println("open file failed, err:", err)
            return
        }
        defer file.Close()
        reader := bufio.NewReader(file)
        for {
            line, err := reader.ReadString('
    ') //注意是字符
            if err == io.EOF {
                fmt.Println("文件读完")
                break
            }
            if err != nil {
                fmt.Println("read file failed, err:", err)
                return
            }
            fmt.Print(line)
        }
    }

    在上面的例子中,只是简单调用reader 中的一个ReadString方法,而Scanner中的内置方法基本与其类似,只是方法名不同而已。

    文件的写入

    os.openFile提供了WriteString和Write两种方法,具体使用哪种根据个人需求。如下

    package main
    
    import (
        "fmt"
        "os"
    )
    
    func main() {
        file, err := os.OpenFile("xx.txt", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
        if err != nil {
            fmt.Println("open file failed, err:", err)
            return
        }
        defer file.Close()
        str1 := "你好"
        str2 := "
    sary"
        file.Write([]byte(str1)) //写入字节切片数据
        file.WriteString(str2)   //直接写入字符串数据
    }

    bufio.Writer 进行文件输出

    bufio 提供了 Writer 来进行高效的输出。实际上是一个内部包含 buffer 的特殊 struct。

    type Writer struct {
        err error
        buf []byte
        n   int
        wr  io.Writer
    }

    buf 这个 field 就是缓冲输出内容的,当满足指定 size 之后,Writer 才会把 buf 中的内容通过 wr 写到输出对象。

    package main
    
    import (
        "bufio"
        "fmt"
        "os"
    )
    
    func main() {
        file, err := os.OpenFile("text.txt", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
        if err != nil {
            fmt.Println("open file failed, err:", err)
            return
        }
        defer file.Close()
        writer := bufio.NewWriter(file)
        for i := 0; i < 10; i++ {
            writer.WriteString("hello
    ") //将数据先写入缓存
        }
        writer.Flush() //将缓存中的内容写入文件
    }

    ioutil 包的文件读写

    最后要提到的文件读写操作的ioutil,不同于上面介绍的方法,ioutil提供的WriteFile, ReadFile 可以直接对文件进行写入和读取,省去了一个打开的过程

    package main
    
    import (
        "fmt"
        "io/ioutil"
    )
    
    func main() {
        str := "hello"
        err := ioutil.WriteFile("text.txt", []byte(str), 0666)
        if err != nil {
            fmt.Println("write file failed, err:", err)
            return
        }
    }

    文件拷贝 

    package main
    
    import (
        "io"
        "log"
        "os"
    )
    
    func main() {
        originalFile, err := os.Open("text.txt")
        if err != nil {
            log.Fatal(err)
        }
        defer originalFile.Close()
    
        newFile, err := os.Create("test_copy.txt")
        if err != nil {
            log.Fatal(err)
        }
        defer newFile.Close()
    
        bytesWritten, err := io.Copy(newFile, originalFile)
        if err != nil {
            log.Fatal(err)
        }
        log.Printf("Copied %d bytes.", bytesWritten)
    
        err = newFile.Sync()
        if err != nil {
            log.Fatal(err)
        }
    }
  • 相关阅读:
    洛谷p1017 进制转换(2000noip提高组)
    Personal Training of RDC
    XVIII Open Cup named after E.V. Pankratiev. Grand Prix of Eurasia
    XVIII Open Cup named after E.V. Pankratiev. Grand Prix of Peterhof.
    Asia Hong Kong Regional Contest 2019
    XVIII Open Cup named after E.V. Pankratiev. Grand Prix of Siberia
    XVIII Open Cup named after E.V. Pankratiev. Ukrainian Grand Prix.
    XVIII Open Cup named after E.V. Pankratiev. GP of SPb
    卜题仓库
    2014 ACM-ICPC Vietnam National First Round
  • 原文地址:https://www.cnblogs.com/saryli/p/13401742.html
Copyright © 2011-2022 走看看