Go: I/O
Go I/O
os
os.File
os.File是Go对文件描述符的抽象os.OpenFile(name string, flag int, perm os.FileMode) (*os.File, error):用指定flag打开文件并返回文件指针,若发生错误则error不为nilflag包括1
2
3
4
5
6
7
8
9
10
11
12
13
14import "syscall"
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.
)只读、只写、读写、追加、创建、不存在才创建、同步写、存在则清空,它们可以使用按位或运算同时存在
必须三选一:指定只读、只写、读写
其它标志可以使用按位或运算配合使用
其中
O_EXCL必须配合O_CREATE一起使用,此时如果文件已存在则会报错FileMode:表示文件类型和文件权限,Linux下用ls -l查询出的权限的分段二进制表示,比如0444FileMode只有在创建文件时有效,在其它情况下使用0即可1
2
3
4
5
6
7
8
9
10
11
12import "io/fs"
// A FileMode represents a file's mode and permission bits.
// The bits have the same definition on all systems, so that
// information about files can be moved from one system
// to another portably. Not all bits apply to all systems.
// The only required bit is [ModeDir] for directories.
// os
type FileMode = fs.FileMode
// fs
type FileMode uint32
Open(name string) (*File, error):只读打开文件Create(name string) (*File, error):创建文件,若文件存在则截断,否则以0o666模式创建NewFile(fd uintptr, name string) *File:将fd封装成*File返回,*File可以使用Fd()获取底层的uintptr*File一定要记得Close(),例如在获取后立刻defer f.Close()
文件I/O错误
os提供一系列方法帮助判断err:IsExist(error)/IsNotExist(error):判断错误是否为文件存在/文件不存在IsPermission(error):判断错误是否为文件权限不足IsTimeout(error):判断错误是否为超时
读写文件
*File提供的方法:Read(b []byte) (n int, error):读取文件内容存储到b,只会覆盖到len(b)ReadAt():可额外传递偏移量(开始读的偏移量而不是字节切片的偏移量)Write(b []byte) (n int, error):将b的内容写入文件,只会写入直到len(b)的内容WriteAt():可额外传递偏移量(开始写的偏移量而不是字节切片的偏移量),和os.O_APPEND互斥WriteString(s string) (n int, error):写入字符串
os.ReadFile(name string) ([]byte, error):读取一个文件的全部内容并返回字节切片os.WriteFile(name string, data []byte, FileMode) error:将字节切片的全部内容写入文件
文件元属性操作
os.Rename(oldpath, newpath string) error:重命名文件os.Delete(name string) error:删除文件os.DeleteAll(dir string) error:递归删除目录下所有文件和目录(*File) Sync():刷盘
目录操作
os.ReadDir(name string) ([]DirEntry, error):读取一个目录,返回切片1
2
3
4
5
6
7
8
9
10
11import "os"
func A() {
dirs, _ := os.ReadDir(".")
for _, dir := range dirs {
dir.Name() // string
dir.IsDir() // bool
dir.Info() // (os.FileInfo, error)
dir.Type() // os.FileMode
}
}或者使用
*File的ReadDir(n int),最多读取n个DirEntry,n为负数时读取全部os.ReadDir()是对它的简单封装os.Mkdir(name string, perm FileMode) error:创建目录os.MkdirAll(path string, perm FileMode) error:类似mkdir -p地创建目录os.Getwd() (string, error):获取工作目录os.Chdir(dir string) error:修改工作目录
环境变量相关
os.Getenv(key string) stringos.Setenv(key, value string) erroros.LookupEnv(key string) (string bool)filepath标准库提供一系列处理文件路径的函数
io与io/fs
I/O接口
io.Reader:只有Read([]byte) (n int, error)方法io.Writer:只有Write([]byte) (n int, error)方法io.Closer:只有Close() error方法io.Seeker:只有Seek(offset int64, whence int) (int64, error)方法io.ReadWriter:Reader与Writer并集io.ReadCloser:Reader | Closerio.WriteCloser:Writer | Closerio.ReadWriteCloser:Writer | Reader | Closerio.ReadSeeker:Reader | Seekerio.ReadSeekCloser:Reader | Seeker | Closer- 更多接口可查阅文档
*os.File实现了上述所有接口
io工具函数
io.Copy(dst Writer, src Reader) (written int64, err error):复制文件,默认使用32K的缓冲区io.CopyBuffer(Writer, Reader, []byte) (int64, error):可以自己指定缓冲区io.CopyN(Writer, Reader, int64):指定最多读取的字节数io.ReadAll(Reader) ([]byte, error):读取所有字节并返回字节切片io.ReadFull(Reader, []byte) (int, error):调用Reader的Read,若长度不足则报错io.MultiReader(...Reader) Reader:串联多个Reader顺序读取io.MultiWriter(...Writer) Writer:并联多个Writer同时写入
fs.FS
fs.FS将一系列文件资源包括网络资源都抽象成fs.FS,FS接口只有一个Open(name string) (File, error)方法- 可以通过
os.DirFS(dir string) fs.FS将目录转化为FS对象 fs.Sub(fsys FS, dir string) (FS, erorr):将文件系统对象的一个子目录再转换为文件系统对象fs提供了很多查找和读取文件的方法:fs.ReadFile(FS, name string) ([]byte, error):读取整个文件fs.Open(name string) (File, error):打开一个文件,根目录为文件系统对象的目录fs.File.Read([]byte) (int, error):读取一个文件读取到字节切片里fs.File.Close() error:关闭文件fs.Glob(FS, pattern string) ([]string, error):模式匹配地查找文件名fs.ValidPath(name string) bool:检查路径是否生效
- 以及很多关于目录的方法:
fs.WalkDir(fsys FS, root string, WalkDirFunc) error:递归遍历目录,root相对于fsys的路径,WalkDirFunc回调用于自定义处理函数fs.ReadDir(FS, string) ([]DirEntry, error):读取目录内容WalkDirFunc:1
func(path string, d DirEntry, err error) error
在回调中需要处理
err,对d进行自定义的处理返回
nil表示继续遍历,fs.SkipDir表示跳过当前的d,fs.SkipAll表示跳过所有的d
- 在仅需要读取和遍历文件或其它资源的情况下,使用
fs比使用os更好
标准输入输出
os包内置声明了三个标准输入输出描述符:Stdin、Stdout、Stdoutos包的这三个描述符本身就是文件,可以使用上述的os、io、fs提供的方法输出和输入- 内置的
print()和println()可以打印,但通常用于测试 fmt包提供许多用于打印的方法:Print()/Println()/Printf()
fmt格式化:%%:百分号%s/%d/%f/%b/%o/%x/%p:与其它语言类似%v与%+v:输出值的原始形式,后者会附加值的字段%q:输出带有双引号的字符串
bufio
bufio接口
bufio标准库用于缓冲读写,适用于大文件,但是bufio是顺序访问,不像os.File那样是随机访问bufio.NewReader(io.Reader) *bufio.Reader:将io.Reader转化为带缓冲的Readerbufio.NewWriter(...) ...:将io.Writer转化为带缓冲的Writerbufio.NewReadWriter(...) ...:将io.ReadWriter转化为带缓冲的ReadWriterbufio.NewScanner(io.Reader) *bufio.Scanner:将io.Reader转化为bufio.Scanner
bufio.Reader
Read(...)...:与*os.File.Read()类似,提供缓冲ReadByte() (byte, error):读取一个字节ReadBytes(delim byte) ([]byte, error):读取到分隔符delimReadString(delim byte) (string, error):读取到分隔符delim,返回stringReadLine() (line []byte, isPrefix bool, error):读取一行Peek(n int) ([]byte, error):预读取n个字节但是不移动指针Reset(io.Reader):复用*bufio.Reader对象,绑定到新的io.Reader
bufio.Writer
- 与
bufio.Reader的方法相对应 Flush() error:刷盘Reset(io.Writer):复用*bufio.Writer对象,绑定到新的io.Writer
bufio.Scanner
Scan() bool:按行扫描,若指针没有到EOF则返回trueText() string:获取当行的文本Err() error:检查扫描中的错误Split(SplitFunc):自定义分割函数,内置的分割函数如下bufio.ScanLines(默认)bufio.ScanWordsbufio.ScanRunesbufio.ScanBytes