• golang 之文件操作


    文件操作要理解一切皆文件。

    Go 在 os 中提供了文件的基本操作,包括通常意义的打开、创建、读写等操作,除此以外为了追求便捷以及性能上,Go 还在 io/ioutil 以及 bufio 提供一些其他函数供开发者使用

    操作File文件类型

    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	追加
    

     os.open循环读取

    package main
    import (
            "os"
            "fmt"
    )
    func main() {
            userFile := "test.txt"
            fin,err := os.Open(userFile)
            defer fin.Close()
            if err != nil {
                    fmt.Println(userFile,err)
                    return
            }
            buf := make([]byte, 1024)
            for{
                    n, _ := fin.Read(buf)
                    if0 == 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 都支持按行读取文件。

    Reader

    package main
    
    import (
    	"bufio"
    	"fmt"
    	"io"
    	"os"
    )
    
    // bufio按行读取示例
    func main() {
    	file, err := os.Open("text.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 (
    	"os"
    	"fmt"
    )
    
    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()
    	str := "你好"
    	file.Write([]byte(str))       //写入字节切片数据
    	file.WriteString(str) //直接写入字符串数据
    }
    

    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 (
    	"os"
    	"fmt"
    	"bufio"
    )
    
    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 (
    	"io/ioutil"
    	"fmt"
    )
    
    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 (
    	"os"
    	"log"
    	"io"
    )
    
    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)
    	}
    }
    

      

      

      

     

     

  • 相关阅读:
    Ajax_ajax模板引擎 ---tmplate.js处理数据和标签拼接
    Ajax_ajax请求中的跨域问题---浏览器不允许ajax跨域获取服务器数据,那我们就用jsonp来实现跨域
    Ajax_jquery库中Ajax方法的使用
    第一阶段冲刺 second day
    第11周周总结
    用户场景分析
    第一阶段冲刺 first day
    第10周周总结
    第9周周总结
    查找水王
  • 原文地址:https://www.cnblogs.com/flash55/p/11110008.html
Copyright © 2020-2023  润新知