Golang - 文件操作


讀文件

Open()

package main

// 打開文件, 只讀的話使用Open()即可, 因爲一樣是通過Openfile實現, 設置打開方式爲只讀
import (
	"fmt"
	"os"
)

func main() {
	file, err := os.Open("./fileA")

	// 錯誤處理
	if err != nil {
		fmt.Println(err)
		return
	}

	// defer延遲關閉文件
	defer file.Close()
}

源碼

// Open opens the named file for reading. If successful, methods on
// the returned file can be used for reading; the associated file
// descriptor has mode O_RDONLY.
// If there is an error, it will be of type *PathError.
func Open(name string) (*File, error) {
	return OpenFile(name, O_RDONLY, 0)
}


file.Read()

// 按照字節讀文件

func readByte(f string, byteLen int) {
	file, err := os.Open(f)

	// 錯誤處理
	if err != nil {
		fmt.Println(err)
		return
	}

	// defer延遲關閉文件
	defer file.Close()

	for {
		var tmp = make([]byte, byteLen)

		_, err := file.Read(tmp) // 按切片大小讀文件

		// 末尾處理
		if err == io.EOF {
			fmt.Println("文件結束了")
			return
		}

		// 錯誤處理
		if err != nil {
			fmt.Println(err)
			return
		}

		fmt.Println(tmp)
	}
}

源碼

// Read reads up to len(b) bytes from the File.
// It returns the number of bytes read and any error encountered.
// At end of file, Read returns 0, io.EOF.
func (f *File) Read(b []byte) (n int, err error) {
	if err := f.checkValid("read"); err != nil {
		return 0, err
	}
	n, e := f.read(b)
	return n, f.wrapErr("read", e)
}


bufio

// ReadLine 逐行讀文件

func ReadLine(f string) {
	file, err := os.Open(f)

	// 錯誤處理
	if err != nil {
		fmt.Println(err)
		return
	}

	// defer延遲關閉文件
	defer file.Close()

	reader := bufio.NewReader(file)

	for {
		str, err := reader.ReadString('\n')

		if err == io.EOF {
			fmt.Println(str)
			return
		}

		if err != nil {
			fmt.Println(err)
			return
		}

		fmt.Print(str)
	}
}

源碼

// NewReader returns a new Reader whose buffer has the default size.
func NewReader(rd io.Reader) *Reader {
	return NewReaderSize(rd, defaultBufSize)
}

// ReadString reads until the first occurrence of delim in the input,
// returning a string containing the data up to and including the delimiter.
// If ReadString encounters an error before finding a delimiter,
// it returns the data read before the error and the error itself (often io.EOF).
// ReadString returns err != nil if and only if the returned data does not end in
// delim.
// For simple uses, a Scanner may be more convenient.
func (b *Reader) ReadString(delim byte) (string, error) {
	bytes, err := b.ReadBytes(delim)
	return string(bytes), err
}


ioutil

// 使用ioutil讀取**文件全部**

func readFile(f string) {
	content, err := ioutil.ReadFile(f)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(string(content))
}

源碼

// ReadFile reads the file named by filename and returns the contents.
// A successful call returns err == nil, not err == EOF. Because ReadFile
// reads the whole file, it does not treat an EOF from Read as an error
// to be reported.
func ReadFile(filename string) ([]byte, error) {
	f, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	// It's a good but not certain bet that FileInfo will tell us exactly how much to
	// read, so let's try it but be prepared for the answer to be wrong.
	var n int64 = bytes.MinRead

	if fi, err := f.Stat(); err == nil {
		// As initial capacity for readAll, use Size + a little extra in case Size
		// is zero, and to avoid another allocation after Read has filled the
		// buffer. The readAll call will read into its allocated internal buffer
		// cheaply. If the size was wrong, we'll either waste some space off the end
		// or reallocate as needed, but in the overwhelmingly common case we'll get
		// it just right.
		if size := fi.Size() + bytes.MinRead; size > n {
			n = size
		}
	}
	return readAll(f, n)
}


寫文件

Openfile

package main

import (
	"fmt"
	"os"
)

func main() {
	// 新建一個文件, 文件名爲fileA, 權限644
	file, err := os.OpenFile("fileA", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) 
	
	// 錯誤處理
	if err != nil {
		fmt.Println(err)
		return
	}

	// 延遲釋放
	defer file.Close()
}

源碼

// OpenFile is the generalized open call; most users will use Open
// or Create instead. It opens the named file with specified flag
// (O_RDONLY etc.) and perm (before umask), if applicable. If successful,
// methods on the returned File can be used for I/O.
// If there is an error, it will be of type *PathError.
func OpenFile(name string, flag int, perm FileMode) (*File, error) {
	testlog.Open(name)
	return openFileNolog(name, flag, perm)
}

// 第一個參數爲文件名
// 	接收字符串
// 第二個參數爲打開的方式
// 	見下表
// 第三個參數爲權限
// 	同linux權限


權限表

權限 描述
os.O_CREATE 創建
os.O_RDONLY 只讀,通常直接使用os.Open方法
os.O_WRONLY 只寫
os.O_RDWR 讀寫
os.O_TRUNC 清空文件
os.O_APPEND 追加

Write()和WriteString()

// 使用WriteString()
func myWrite1(f, str string) {
	file, err := os.OpenFile(f, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) // 新建一個文件, 文件名爲fileA, 只讀權限

	if err != nil {
		fmt.Println(err)
		return
	}

	defer file.Close()

	file.WriteString(str)
}

// 使用Write()
func myWrite2(f, str string) {
	file, err := os.OpenFile(f, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) // 新建一個文件, 文件名爲fileA, 只讀權限

	if err != nil {
		fmt.Println(err)
		return
	}

	defer file.Close()

	file.Write([]byte(str))
}

// 調用
func main(){
	myWrite1("fileA", "abc中國")
	myWrite2("fileB", "中國abc")
}

bufio.NewWriter

func myWrite3(f, str string) {
	// 新建一個文件, 文件名爲fileA, 權限644
	file, err := os.OpenFile(f, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)

	// 錯誤處理
	if err != nil {
		fmt.Println(err)
		return
	}

	// 延遲釋放
	defer file.Close()

	writer := bufio.NewWriter(file)

	for i := 0; i < 10; i++ {
		writer.WriteString(str) // 先寫入緩存
	}

	writer.Flush() // 從緩存寫入文件
}


ioutil.WriteFile

package main

import (
	"fmt"
	"io/ioutil"
)

func main() {
	// 設置要寫入的字符串
	str := "abc"

	err := ioutil.WriteFile("fileA", []byte(str), 0644)
	if err != nil {
		fmt.Println(err)
		return
	}
}

源碼

// WriteFile writes data to a file named by filename.
// If the file does not exist, WriteFile creates it with permissions perm;
// otherwise WriteFile truncates it before writing.
func WriteFile(filename string, data []byte, perm os.FileMode) error {
	f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
	if err != nil {
		return err
	}
	n, err := f.Write(data)
	if err == nil && n < len(data) {
		err = io.ErrShortWrite
	}
	if err1 := f.Close(); err == nil {
		err = err1
	}
	return err
}


練習

copyFile

實現cat命令

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章