打开和关闭文件
在Go语言中使用os.Open()
可以打开一个文件,返回一个文件指针*file
和错误信息err
,对得到的文件指针调用close()
方法即可关闭文件。
如下:
package main
import (
"fmt"
"os"
)
func main() {
file, _ := os.Open("./main.go")
fmt.Printf("%T\n", file)
file.Close()
}
为了防止文件忘记关闭,我们通常使用defer注册文件关闭语句。
如下:
package main
import (
"fmt"
"os"
)
func main() {
file, _ := os.Open("./main.go")
fmt.Printf("%T\n", file)
defer file.Close()
}
读取文件
file.read()
read
方法定义如下:
func (f *File) Read(b []byte) (n int, err error)
该方法接受一个字节类型的参数,返回读取的字节数和可能的错误,读到文件末尾会返回0
和io.EOF
。
如下:
package main
import (
"fmt"
"os"
)
func main() {
file, err := os.Open("./main.go")
if err != nil {
fmt.Printf("File Open failed.err:%s\n", err)
return
}
defer file.Close()
// 定义读取的字节数
tmp := make([]byte, 128)
// 按字节读取文件
n, err := file.Read(tmp)
if err != nil {
fmt.Printf("File Read Failed.err:%s\n", err)
return
}
// 打印读取的字节数
fmt.Println(n)
// 打印读取的内容
fmt.Println(string(tmp[:n]))
}
上面这种读取方式是按设定的字节读取,如果文本中总字节数少于设定的,那么就可以把文本全部读取出来,如果文本总字节数大于设定的字节数,那么文本就不能被全部读取。
这个时候可以使用循环来读取所有文本,如下:
package main
import (
"fmt"
"io"
"os"
)
func main() {
file, err := os.Open("./main.go")
if err != nil {
fmt.Printf("File Open failed.err:%s\n", err)
return
}
defer file.Close()
// 定义读取的字节数
tmp := make([]byte, 128)
for {
// 按字节读取文件
n, err := file.Read(tmp)
// 如果文件已经读完了,就退出
if err == io.EOF {
// fmt.Printf("文件读完了\n")
break
}
if err != nil {
fmt.Printf("File Read Failed.err:%s\n", err)
return
}
// 打印读取的内容
fmt.Print(string(tmp[:n]))
}
}
bufio读取文件
bufio
是带缓存功能的I/O操作。用其读取文件的示例如下:
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func main() {
// 打开文件
file, err := os.Open("./main.go")
if err != nil {
fmt.Printf("Open File Failed.err:%s\n", err)
return
}
defer file.Close()
// 返回一个新的reader,用NewReader有默认大小
reader := bufio.NewReader(file)
// 用循环逐行读取文件
for {
line, err := reader.ReadString('\n')
if err == io.EOF {
// fmt.Printf("File Has Been Read\n")
break
}
if err != nil {
fmt.Printf("Read File Failed.err:%s\n", err)
}
fmt.Print(line)
}
}
上面是用的bufio.NerReader()
来获取一个新的reader
,再用这个对象来读取文件的。除此之外还可以使用bufio.NewReaderSize
来获取一个新的reader
,不同之处在于NewReaderSize
可以设置缓冲区的大小,语法如下:
reader := bufio.NewReaderSize(fileObj, size)
ioutil读取整个文件
io/ioutil
包的ReadFile
方法能够读取完整的文件,只需要将文件名作为参数传入。
package main
import (
"fmt"
"io/ioutil"
)
func main() {
content, err := ioutil.ReadFile("./main.go")
if err != nil {
fmt.Printf("Read File Failed.err:%s\n", err)
return
}
fmt.Println(string(content))
}
写入文件
os.OpenFile()
函数能够以指定模式打开文件,从而实现文件写入相关功能。
func OpenFile(name string, flag int, perm FileMode) (*File, error) {
...
}
其中:
name
:要打开的文件名 flag
:打开文件的模式。 模式有以下几种:
含义 | 模式 |
---|---|
只写 | os.O_WRONLY |
创建文件 | os.O_CREATE |
只读 | os.O_RDONLY |
读写 | os.O_RDWR |
清空 | os.O_TRUNC |
追加 | os.O_APPEND |
perm
:文件权限,一个八进制数。r(读)04,w(写)02,x(执行)01。
比如:
file,err := os.OpenFile("xx.txtx",os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
Write和WriteString
Write
写入的是字节切片数据,WriteString
写入的是字符串数据。
如下:
package main
import (
"fmt"
"os"
)
func main() {
file, err := os.OpenFile("a.txt", os.O_APPEND|os.O_CREATE, 0644)
if err != nil {
fmt.Printf("Open File Failed.err:%s\n", err)
return
}
defer file.Close()
// 写入
str := "牛逼的Go语言\n"
// 用Write写入
file.Write([]byte(str))
// 用WriteString写入
file.WriteString(str)
}
bufio写入文件
使用bufio.NewWriter()
写入文件,需要在最后Flush()
。
如下:
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
file, err := os.OpenFile("b.txt", os.O_APPEND|os.O_CREATE, 0644)
if err != nil {
fmt.Printf("Open File Failed.err:%s\n", err)
return
}
defer file.Close()
// 用bufio.NewWrite返回一个writer
writer := bufio.NewWriter(file)
writer.WriteString("这是一个bufio的写入测试")
writer.Flush()
}
同理除了使用NewWriter
,还可以使用NewWriterSize
。
ioutil写入文件
前面介绍ioutil.ReadFile
可以读取整个文件,另外ioutil.WriterFile
也可以一次性将内容写入文件。
语法如下:
err := ioutil.WriterFile("xxx.txt", []byte(str), 0644)
如下:
package main
import (
"fmt"
"io/ioutil"
)
func main() {
str := `
融融的三月,万物尽苏醒
蜿蜒曲折的小路承载着儿时的记忆
鸟儿在树梢吟唱,歌颂着新春好光景
阳光明媚,和着泥土和花香
舒展手臂抱向天空,拥抱朵朵云彩
大地又重新充满了生机。
`
err := ioutil.WriteFile("./c.txt", []byte(str), 0644)
if err != nil {
fmt.Printf("Write File Failed.err:%s\n", err)
return
}
}
日志库
需求
- 支持往不同地方写日志
- 日志分级别
- Debug
- Trace
- Info
- Warning
- Error
- Fatal
- 日志支持开关控制
- 日志记录包含时间、行号、文件名、日志级别、日志信息
- 日志文件要切割
- 按大小切割
- 按时间切割