Go读写文件
读文件
os.File 实现了Reader接口
// io.Reader
type Reader interface {
Read(p []byte) (n int, err error)
}
// os.File
// File represents an open file descriptor.
type File struct {
*file // os specific
}
// 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)
}
使用Read 方法读取文件内容到字节slice中。
package main
import (
"log"
"os"
)
func main() {
var path string = "/Users/xinxingegeya/temp/helloworld.txt"
// Open file for reading
file, err := os.Open(path)
if err != nil {
log.Fatal(err)
}
defer file.Close()
// Read up to len(b) bytes from the File
// Zero bytes written means end of file
// End of file returns error type io.EOF
byteSlice := make([]byte, 16)
bytesRead, err := file.Read(byteSlice)
if err != nil {
log.Fatal(err)
}
log.Printf("Number of bytes read: %d\n", bytesRead)
log.Printf("Data read: %s\n", byteSlice)
}
使用io包的方法 - io.ReadFull 和 io.ReadAtLeast
package main
import (
"io"
"log"
"os"
)
func main() {
var path string = "/Users/xinxingegeya/temp/helloworld.txt"
// Open file for reading
file, err := os.Open(path)
if err != nil {
log.Fatal(err)
}
// The file.Read() function will happily read a tiny file in to a large
// byte slice, but io.ReadFull() will return an
// error if the file is smaller than the byte slice.
byteSlice := make([]byte, 2)
numBytesRead, err := io.ReadFull(file, byteSlice)
if err != nil {
log.Fatal(err)
}
log.Printf("Number of bytes read: %d\n", numBytesRead)
log.Printf("Data read: %s\n", byteSlice)
///
// ReadAtLeast 从 r 中读取数据到 buf 中,要求至少读取 min 个字节
// 返回读取的字节数 n 和读取过程中遇到的任何错误
// 如果 n < min,则 err 返回 ErrUnexpectedEOF
// 如果 r 中无可读数据,则 err 返回 EOF
// 如果 min 大于 len(buf),则 err 返回 ErrShortBuffer
// 只有当 n >= min 时 err 才返回 nil
byteSliceAtLeast := make([]byte, 512)
minBytes := 8
// io.ReadAtLeast() will return an error if it cannot
// find at least minBytes to read. It will read as
// many bytes as byteSliceAtLeast can hold.
numBytesReadAtLeast, err := io.ReadAtLeast(file, byteSliceAtLeast, minBytes)
if err != nil {
log.Fatal(err)
}
log.Printf("Number of bytes read: %d\n", numBytesReadAtLeast)
log.Printf("Data read: %s\n", byteSliceAtLeast)
}
使用ioutil工具读取文件
package main
import (
"fmt"
"io/ioutil"
"os"
)
func main() {
var path string = "/Users/xinxingegeya/temp/helloworld.txt"
f, err := os.Open(path)
if err != nil {
fmt.Println(err)
}
// ioutil.ReadAll() will read every byte
// from the reader (in this case a file),
// and return a slice of unknown slice
data, err := ioutil.ReadAll(f)
if err != nil {
fmt.Println(err)
}
fmt.Println("Number of bytes read:", len(data))
//ioutil.ReadFile 参数为 文件的路径,然后返回一个未知大小的slice
data2, err := ioutil.ReadFile(path)
fmt.Println("Number of bytes read:", len(data2))
}
使用缓冲读取文件
package main
import (
"bufio"
"fmt"
"log"
"os"
)
func main() {
var path string = "/Users/xinxingegeya/temp/helloworld.txt"
file, err := os.Open(path)
if err != nil {
fmt.Println(err)
}
bufferedReader := bufio.NewReader(file)
// Peek 返回缓存的一个切片,该切片引用缓存中前 n 字节数据
// 该操作不会将数据读出,只是引用
// 引用的数据在下一次读取操作之前是有效的
// 如果引用的数据长度小于 n,则返回一个错误信息
// 如果 n 大于缓存的总大小,则返回 ErrBufferFull
// 通过 Peek 的返回值,可以修改缓存中的数据
// 但是不能修改底层 io.Reader 中的数据
// Get bytes without advancing pointer
byteSlice := make([]byte, 5)
byteSlice, err = bufferedReader.Peek(5)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Peeked at 5 bytes: %s\n", byteSlice)
// Read 从 b 中读出数据到 p 中,返回读出的字节数
// 如果 p 的大小 >= 缓存的总大小,而且缓存不为空
// 则只能读出缓存中的数据,不会从底层 io.Reader 中提取数据
// 如果 p 的大小 >= 缓存的总大小,而且缓存为空
// 则直接从底层 io.Reader 向 p 中读出数据,不经过缓存
// 只有当 b 中无可读数据时,才返回 (0, io.EOF)
// Read and advance pointer
numBytesRead, err := bufferedReader.Read(byteSlice)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Read %d bytes: %s\n", numBytesRead, byteSlice)
// ReadByte 从 b 中读出一个字节并返回
// 如果 b 中无可读数据,则返回一个错误
// Ready 1 byte. Error if no byte to read
myByte, err := bufferedReader.ReadByte()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Read 1 byte: %c\n", myByte)
// ReadBytes 在 b 中查找 delim 并读出 delim 及其之前的所有数据
// 如果 ReadBytes 在找到 delim 之前遇到错误
// 则返回遇到错误之前的所有数据,同时返回遇到的错误(通常是 io.EOF)
// 只有当 ReadBytes 找不到 delim 时,err 才不为 nil
// 对于简单的用途,使用 Scanner 可能更方便
// Read up to and including delimiter
// Returns byte slice
dataBytes, err := bufferedReader.ReadBytes('\n')
if err != nil {
log.Fatal(err)
}
fmt.Printf("Read bytes: %s\n", dataBytes)
// ReadString 功能同 ReadBytes,只不过返回的是一个字符串
// Read up to and including delimiter
// Returns string
dataString, err := bufferedReader.ReadString('\n')
if err != nil {
log.Fatal(err)
}
fmt.Printf("Read string: %s\n", dataString)
}
使用Scanner读取文件
package main
import (
"bufio"
"fmt"
"log"
"os"
)
// bufio.ScanBytes 是一个“切分函数”
// 用来找出 data 中的单个字节并返回
// func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error)
// ScanRunes 是一个“切分函数”
// 用来找出 data 中的单个 UTF8 字符的编码并返回
// 如果 UTF8 解码出错,则返回的 U+FFFD 会被做为 "\xef\xbf\xbd" 返回
// 这使得用户无法区分“真正的U+FFFD字符”和“解码错误的返回值”
// func ScanRunes(data []byte, atEOF bool) (advance int, token []byte, err error)
// ScanLines 是一个“切分函数”
// 用来找出 data 中的单行数据并返回(包括空行)
// 行尾标记可能是 \n 或 \r\n(返回值不包括行尾标记)
// func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error)
// ScanWords 是一个“切分函数”
// 用来找出 data 中的单词
// 单词以空白字符分隔,空白字符由 unicode.IsSpace 定义
// func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error)
func main() {
var path string = "/Users/xinxingegeya/temp/helloworld.txt"
// Open file and create scanner on top of it
file, err := os.Open(path)
if err != nil {
log.Fatal(err)
}
scanner := bufio.NewScanner(file)
// Default scanner is bufio.ScanLines. Lets use ScanWords.
// Could also use a custom function of SplitFunc type
scanner.Split(bufio.ScanWords)
// Scan for next token.
success := scanner.Scan()
if success == false {
// Err 返回扫描过程中遇到的非 EOF 错误
// 供用户调用,以便获取错误信息
err = scanner.Err()
if err == nil {
log.Println("Scan completed and reached EOF")
} else {
log.Fatal(err)
}
}
// Get data from scan with Bytes() or Text()
fmt.Println("First word found:", scanner.Text())
// Call scanner.Scan() again to find next token
//循环读取文件
//scanner.Scan() 返回的结果作为循环条件
for scanner.Scan() {
fmt.Println("Word found:", scanner.Text())
}
// 如果scan 到文件末尾或者发生异常,就会结束
}
写文件
示例代码,
package main
import (
"fmt"
"os"
)
/**
* 判断文件是否存在 存在返回 true 不存在返回false
*/
func checkFileIsExist(filename string) bool {
var exist = true
if _, err := os.Stat(filename); os.IsNotExist(err) {
exist = false
}
return exist
}
func main() {
// 创建文件
var path string = "/Users/xinxingegeya/temp/helloworld.txt"
var f *os.File
var err error
if checkFileIsExist(path) {
// Use these attributes individually or combined
// with an OR for second arg of OpenFile()
// e.g. os.O_CREATE|os.O_APPEND
// or os.O_CREATE|os.O_TRUNC|os.O_WRONLY
// os.O_RDONLY // Read only
// os.O_WRONLY // Write only
// os.O_RDWR // Read and write
// os.O_APPEND // Append to end of file
// os.O_CREATE // Create is none exist
// os.O_TRUNC // Truncate file when opening
f, err = os.OpenFile(path, os.O_RDWR|os.O_APPEND, 0666) //打开文件
} else {
f, err = os.Create(path) //创建文件
fmt.Println("file not exist,create file")
}
defer f.Close()
if err != nil {
fmt.Println(err)
return
}
n, err := f.WriteString("hello world\n")
if err != nil {
//write /Users/xinxingegeya/temp/helloworld.txt: bad file descriptor
fmt.Println(err)
return
} else {
fmt.Printf("write string: %d bytes\n", n)
}
n2, err := f.Write([]byte("hello world"))
if err != nil {
fmt.Println(err)
return
} else {
fmt.Printf("write data: %d bytes\n", n2)
}
}
使用io.WriteString写文件
package main
import (
"fmt"
"io"
"os"
)
func main() {
// 创建文件
var path string = "/Users/xinxingegeya/temp/helloworld.txt"
f, err := os.OpenFile(path, os.O_RDWR|os.O_APPEND, 0666) //打开文件
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
// WriteString 将字符串 s 写入到 w 中
// 返回写入的字节数和写入过程中遇到的任何错误
// 如果 w 实现了 WriteString 方法
// 则调用 w 的 WriteString 方法将 s 写入 w 中
// 否则,将 s 转换为 []byte
// 然后调用 w.Write 方法将数据写入 w 中
// func WriteString(w Writer, s string) (n int, err error)
n, err := io.WriteString(f, "hello world\n")
if err != nil {
fmt.Println(err)
return
} else {
fmt.Printf("write string: %d bytes", n)
}
}
使用bufio写文件
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
// 创建文件
var path string = "/Users/xinxingegeya/temp/helloworld.txt"
f, err := os.OpenFile(path, os.O_RDWR|os.O_APPEND, 0666) //打开文件
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
//使用 bufio.NewWriter 写入文件
//默认缓存大小:defaultBufSize=4096
w := bufio.NewWriter(f) //创建新的 Writer 对象
var count = 0
for i := 0; i < 1000; i++ {
n, _ := w.WriteString("hello world\n")
count += n
}
fmt.Printf("write string: %d bytes", count)
w.Flush()
}
使用ioutil.WriteFile写文件
package main
import (
"fmt"
"io/ioutil"
)
func main() {
var path string = "/Users/xinxingegeya/temp/helloworld.txt"
//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.
err := ioutil.WriteFile(path, []byte("hello world"), 0666)
if err != nil {
fmt.Println(err)
}
}
==========END==========