Dawn's Blogs

分享技术 记录成长

0%

GO学习笔记 (2) 文件操作

基本介绍

os.File封装所有的文件相关操作,File是一个结构体。File代表一个打开文件的对象。

文件基本操作

打开/关闭文件

os.Open

1
2
3
4
5
6
7
// 打开文件
// Open打开一个文件用于读取。如果操作成功,返回的文件对象的方法可用于读取数据。如果出错,错误底层类型是*PathError。
func Open(name string) (file *File, err error)

// 关闭文件
// Close关闭文件f,使文件不能用于读写。它返回可能出现的错误。
func (f *File) Close() error

Open返回的是File结构体指针

os.OpenFile

1
func OpenFile(name string, flag int, perm FileMode) (file *File, err error)

OpenFile是一个更一般性的文件打开函数,大多数调用者都应用Open或Create代替本函数。它会使用指定的选项(如O_RDONLY等)、指定的模式(如0666等)打开指定名称的文件。如果操作成功,返回的文件对象可用于I/O。如果出错,错误底层类型是*PathError

  • flag参数是文件打开模式
1
2
3
4
5
6
7
8
9
10
const (
O_RDONLY int = syscall.O_RDONLY // 只读模式打开文件
O_WRONLY int = syscall.O_WRONLY // 只写模式打开文件
O_RDWR int = syscall.O_RDWR // 读写模式打开文件
O_APPEND int = syscall.O_APPEND // 写操作时将数据附加到文件尾部
O_CREATE int = syscall.O_CREAT // 如果不存在将创建一个新文件
O_EXCL int = syscall.O_EXCL // 和O_CREATE配合使用,文件必须不存在
O_SYNC int = syscall.O_SYNC // 打开文件用于同步I/O
O_TRUNC int = syscall.O_TRUNC // 如果可能,打开时清空文件
)
  • FileMode代表文件打开的权限,r-w-x,只在Linux下有效

读文件

带缓冲的写入bufio.Reader

bufio.Reader是一个结构体,实现了给一个io.Reader接口对象附加缓冲。默认缓冲区大小位4096B

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package main

import (
"bufio"
"fmt"
"io"
"os"
)

func main() {
filePath := "F:/gopath/src/LearnGoLang/File/Reader/Test.txt"
file, err := os.Open(filePath)

if err != nil {
fmt.Println("open file error =", err)
return
}

defer file.Close() // main函数推出前关闭文件,否则会内存泄漏

// 创建一个带缓冲的*Reader
// 默认缓冲区大小位4096B
// const (
// defaultBufSize = 4096
// )
reader := bufio.NewReader(file)

// 循环读取文件内容
for {
str, err := reader.ReadString('\n') // 读到换行符接收
if err == io.EOF { // io.EOF表示文件末尾
break
}
fmt.Print(str)
}
}

一次性读取文件ioutil.ReadFile

1
func ReadFile(filename string) ([]byte, error)

使用ioutil.ReadFile函数,ReadFile 从filename指定的文件中读取数据并返回文件的内容。成功的调用返回的err为nil而非EOF。因为本函数定义为读取整个文件,它不会将读取返回的EOF视为应报告的错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import (
"fmt"
"io/ioutil"
)

func main() {
fileName := "F:/gopath/src/LearnGoLang/File/Reader/Test.txt"
content, err := ioutil.ReadFile(fileName) // content类型是[]byte

if err != nil {
fmt.Printf("read file error = %v", err)
}

fmt.Printf("%s", content)
}

写文件

带缓冲的写入bufio.Writer

bufio.Writer是一个结构体,Writer实现了为io.Writer接口对象提供缓冲。如果在向一个Writer类型值写入时遇到了错误,该对象将不再接受任何数据,且所有写操作都会返回该错误。在说有数据都写入后,调用者有义务调用Flush方法以保证所有的数据都交给了下层的io.Writer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package main

import (
"bufio"
"fmt"
"os"
)

func main() {
filePath := "F:/gopath/src/LearnGoLang/File/Writer/Test.txt"
file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666)

if err != nil {
fmt.Printf("open file error = %v", err)
return
}

// main函数退出时关闭文件
defer file.Close()

str := "Hello World\n"

// 写入时,使用带缓冲的*Writer
writer := bufio.NewWriter(file)
writer.WriteString(str)

// 因为write是带缓冲的,因此使用WriteString是先写入到缓冲区的
// Flush方法将缓冲中的数据写入下层的io.Writer接口。
writer.Flush()
}

一次性写入文件ioutil.WriteFile

1
func WriteFile(filename string, data []byte, perm os.FileMode) error

函数向filename指定的文件中写入数据。如果文件不存在将按给出的权限创建文件,否则在写入数据之前清空文件。

判断文件/目录是否存在os.Stat

1
func Stat(name string) (fi FileInfo, err error)

Stat返回一个描述name指定的文件对象的FileInfo。如果指定的文件对象是一个符号链接,返回的FileInfo描述该符号链接指向的文件的信息,本函数会尝试跳转该链接。如果出错,返回的错误值为*PathError类型。

1
2
3
4
5
6
7
8
type FileInfo interface {
Name() string // 文件的名字(不含扩展名)
Size() int64 // 普通文件返回值表示其大小;其他文件的返回值含义各系统不同
Mode() FileMode // 文件的模式位
ModTime() time.Time // 文件的修改时间
IsDir() bool // 等价于Mode().IsDir()
Sys() interface{} // 底层数据来源(可以返回nil)
}

FileInfo用来描述一个文件对象。

文件拷贝io.Copy

1
func Copy(dst Writer, src Reader) (written int64, err error)

将src的数据拷贝到dst,直到在src上到达EOF或发生错误。返回拷贝的字节数和遇到的第一个错误。

对成功的调用,返回值err为nil而非EOF,因为Copy定义为从src读取直到EOF,它不会将读取到EOF视为应报告的错误。如果src实现了WriterTo接口,本函数会调用src.WriteTo(dst)进行拷贝;否则如果dst实现了ReaderFrom接口,本函数会调用dst.ReadFrom(src)进行拷贝。