文章目录
- 文件信息接口os.FileInfo
- 文件的常规操作 (os包)
- 文件的读取和写入 (io及os包)
- ioutil包
- bufio包
一、文件信息
os.FileInfo接口
接口属性
type FileInfo interface {
Name() string // 文件的名字
Size() int64 // 普通文件返回值表示其大小;其他文件的返回值含义各系统不同
Mode() FileMode // 文件的模式位 (例-rw-rw-r--)
ModTime() time.Time // 文件的修改时间
IsDir() bool // 等价于Mode().IsDir()
Sys() interface{} // 底层数据来源(可以返回nil)
}
os.fileStat结构体实现了FileInfo接口的所有方法
type fileStat struct {
name string
size int64
mode FileMode
modTime time.Time
sys syscall.Stat_t
}
示例
fileInfo, err := os.Stat("./aa.txt")
if err != nil{
fmt.Println(err)
return
}
fmt.Printf("%T: %v", fileInfo, fileInfo) // *os.fileStat: &{aa.txt 23 ...}
fmt.Println(fileInfo.Name()) // aa.txt
fmt.Println(fileInfo.IsDir()) // false
fmt.Println(fileInfo.Size()) // 23
fmt.Println(fileInfo.Mode()) // -rw-rw-r--
fmt.Println(fileInfo.ModTime()) // 2019-02-15 14:44:39.745 +0800 CST
文件路径相关函数
路径相关的函数有两个包,path
和 path/filepath
,
两个包内有一些相同的函数,如IsAbs()
、Join()
、Dir()
filepath
中的函数兼容各个操作系统,涉及到windows系统路径操作时,应该使用filepath
包
-
filepath.Rel(basepath, targpath string) (string, error)
获取相对路径 -
filepath.Abs(path string) (string, error)
获取绝对路径,如果path不是绝对路径,会加入当前工作目录以使之成为绝对路径。 -
path.Join(elem ...string) string
路径拼接 -
path.IsAbs(path string) bool
判断文件是否是绝对路径 -
path.Dir(path string) string
获取目录
二、文件的常规操作
创建目录 如果存在则失败
-
os.Mkdir(name string, perm FileMode) error
- 仅创建一层
- 相当于
linux
命令mkdir
-
os.MkdirAll(path string, perm FileMode) error
- 创建多层
- 相当于
linux
命令mkdir -p
创建文件 如果存在会覆盖
-
os.Create(name string) (file *File, err error)
- 底层调用
os.OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
- 采用模式
0666
(任何人都可读写,不可执行) - 如果文件存在会清空它
- 底层调用
打开文件
-
os.Open(name string) (file *File, err error)
- 底层调用
OpenFile(name, O_RDONLY, 0)
- 以只读的方式打开文件
- 底层调用
-
os.OpenFile(name string, flag int, perm FileMode) (file *File, err error)
-
perm
可为0666
、0777
等 -
flag
是os
包中定义的常量:
-
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 // 如果可能,打开时清空文件
)
关闭文件
-
file.Close() error
- *File指针的方法
- 程序与文件之间的连接断开
删除文件或目录
-
os.Remove(name string) error
- 只删除一层
- 相当于
linux
命令rm
-
os.RemoveAll(path string) error
- 删除path指定的文件,或目录及它包含的任何下级对象
- 相当于
linux
命令rm -r
三、文件的读写操作
读取文件
-
os.Open(filename)
-->*File
-
file.Read([]byte)
-->n, err
- 单次读取的字节数最大为
[]byte
的长度 -
n
为实际读取到的字节数 - 读取到末尾时
err
为EOF(end of file)
- 单次读取的字节数最大为
-
file.Close()
关闭文件
示例:
//step1:打开文件
fileName := ".text.txt"
file, err := os.Open(fileName)
if err != nil {
fmt.Println("打开错误", err)
return
}
//step2:读/写
//从file中读取最多len(bs)个字节,存入bs切边中,n是实际读取的数量
bs := make([]byte, 1024, 1024)
for {
n, err := file.Read(bs)
if n == 0 || err == io.EOF {
fmt.Println("读取结束")
break
}
fmt.Println(string(bs[:n]))
}
//step3:关闭文件
file.Close()
写入文件
写入文件与读取类似
-
os.Open(filename)
-->*File
-
file.Write([]byte)
-->n, err
- 将
[]byte
中的数据写入文件
- 将
-
file.WriteString(string)
-->n, err
- 将
string
写入文件
- 将
file.Close()
文件复制
-
io.Copy(dst Writer, src Reader) (written int64, err error)
- dst和src为实现了接口io.Writer和io.Reader的实例
示例:
func copyFile(srcFile, destFile string) (int64, error) {
file1, err := os.Open(srcFile)
if err != nil {
return 0, err
}
file2, err := os.OpenFile(destFile, os.O_WRONLY|os.O_CREATE, os.ModePerm)
if err != nil {
return 0, err
}
defer file1.Close()
defer file2.Close()
return io.Copy(file2, file1)
}
四、ioutil包
-
ReadFile()
-->([]byte, error)
- 读取所有数据,返回字节数组
-
WriteFile(filename string, data []byte, perm os.FileMode)
-->error
- 文件不存在则创建文件,存在则清空文件
- os.FileMode可以直接用
0666
或者0777
-
ReadDir()
-->([]os.FileInfo, error)
- 读取一个目录下的字内容,目录或文件,但是只有一层
- 返回一个
os.FileInfo
切片
示例:
data, err := ioutil.ReadFile("aa.txt")
fmt.Println(string(data))
if err != nil {
fmt.Println(err)
return
}
err = ioutil.WriteFile("bb.txt", data, 0666)
if err != nil {
fmt.Println(err)
return
}
fileInfos, err := ioutil.ReadDir(".")
if err != nil {
fmt.Println(err)
return
}
for i := range fileInfos {
fmt.Println(i, fileInfos[i].IsDir(), fileInfos[i].Name())
}
五、bufio包
-
bufio
包实现了有缓冲的I/O
-
bufio
封装了一个Reader
݊及Writer
结构体,分别实现了io.Reader
和io.Writer
接口 - 通过对对
io
模块的封装,提供了带有缓冲的io
操作,减小了大块数据读写的io开销
io.Reader和io.Writer
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
os.Open(name string) (*File, error)
返回的文件指针就实现了io.Reader
bufio.Reader结构体
-
NewReader(rd io.Reader) *Reader
-
NewReader
创建一个具有默认大小缓冲、从r
读取的*Reader
-
-
Reader.Read(p []byte) (n int, err error)
-
Read
读取数据写入p
。本方法返回写入p
的字节数 - 返回值n可能小于
len(p)
,读取到达结尾时,返回值n
将为0
而err
将为io.EOF
- 类似
File.Read()
方法
-
示例:
s := strings.NewReader("ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
br := bufio.NewReader(s)
b := make([]byte, 20)
n, err := br.Read(b)
fmt.Printf("%-20s %-2v %v\n", b[:n], n, err) // ABCDEFGHIJKLMNOPQRST 20 <nil>
n, err = br.Read(b)
fmt.Printf("%-20s %-2v %v\n", b[:n], n, err) // UVWXYZ1234567890 16 <nil>
n, err = br.Read(b)
fmt.Printf("%-20s %-2v %v\n", b[:n], n, err) // 0 EOF
-
Reader.ReadBytes(delim byte) (line []byte, err error)
-
delim
是delimiter
的缩写意为定位符 -
ReadBytes
读取直到第一次遇到delim
字节,返回一个包含已读取的数据和delim
字节的切片
-
示例:
s := strings.NewReader("ABCDEFG\n123456\n")
br := bufio.NewReader(s)
for {
sli, err := br.ReadBytes('\n')
if err err == io.EOF {
break
}
fmt.Println(sli)
}
// [65 66 67 68 69 70 71 10]
// [49 50 51 52 53 54 10]
-
Reader.ReadString(delim byte) (line string, err error)
- 返回的是字符串类型
示例:
s := strings.NewReader("ABCDEFG\n123456\n")
br := bufio.NewReader(s)
for {
s, err := br.ReadString('\n')
if err err == io.EOF {
break
}
fmt.Print(s)
}
// ABCDEFG
// 123456
bufio.Writer结构体
-
NewWriter(w io.Writer) *Writer
-
NewWriter
创建一个具有默认大小缓冲、写入w
的*Writer
-
-
Writer.Write(p []byte) (nn int, err error)
-
Write
将p
的内容写入缓冲。返回写入的字节数。如果返回值nn < len(p)
,还会返回一个错误说明原因 - 类似
File.Write()
方法
-
-
Writer.WriteString(s string) (int, error)
- 写入一个字符串,返回写入的字节数
-
Writer.Flush() error
- Flush方法将缓冲中的数据输出
示例:
file1, _ := os.Open("aa.txt")
defer file1.Close()
reader := bufio.NewReader(file1)
file2, _ := os.Create("cc.txt")
defer file2.Close()
writer := bufio.NewWriter(file2)
for {
bs, err := reader.ReadBytes('\n')
if err == io.EOF {
fmt.Println("读取完毕")
break
}
writer.Write(bs)
writer.Flush()
}
bufio.Scanner结构体
-
NewScanner(r io.Reader) *Scanner
- 创建并返回一个从
r
读取数据的Scanner
,默认的分割函数是ScanLines
- 通过
Scanner.Split(split SplitFunc)
方法,可以为Scanner
指定splitFunc
- Scanner可以通过plitFunc将
r
中的数据拆分为多个token,然后通过Scanner.Scan()
依次读取
- 创建并返回一个从
-
bufio
中提供的默认splitFunc
:-
ScanBytes
,按照byte
进程拆分 -
ScanRunes
,按照行("\n")
进程拆分 -
ScanWords
,按照utf-8
字符进行拆分 -
ScanLines
,按照单词(" ")
进程拆分
-
- 常用方法
Split(split SplitFunc)
Scan() bool
Text() string
Bytes() []byte
示例:
scanner := bufio.NewScanner(os.Stdin)
scanner.Split(bufio.ScanLines)
for scanner.Scan() {
if scanner.Text() == "q" {
break
}
fmt.Println(scanner.Text()) // Println will add back the final '\n'
}
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, "reading standard input:", err)
}
网友评论