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('\n') //注意是字符
		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\n") //將數據先寫入緩存
	}
	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)
	}
}

  

  

  

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM