打开和关闭文件
在Go语言中使用os.Open()可以打开一个文件,返回一个文件指针*file和错误信息err,对得到的文件指针调用close()方法即可关闭文件。
如下:
package mainimport ("fmt""os")func main() {file, _ := os.Open("./main.go")fmt.Printf("%T\n", file)file.Close()}
为了防止文件忘记关闭,我们通常使用defer注册文件关闭语句。
如下:
package mainimport ("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 mainimport ("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 mainimport ("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 mainimport ("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 mainimport ("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 mainimport ("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 mainimport ("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返回一个writerwriter := bufio.NewWriter(file)writer.WriteString("这是一个bufio的写入测试")writer.Flush()}
同理除了使用NewWriter,还可以使用NewWriterSize。
ioutil写入文件
前面介绍ioutil.ReadFile可以读取整个文件,另外ioutil.WriterFile也可以一次性将内容写入文件。
语法如下:
err := ioutil.WriterFile("xxx.txt", []byte(str), 0644)
如下:
package mainimport ("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
- 日志支持开关控制
- 日志记录包含时间、行号、文件名、日志级别、日志信息
- 日志文件要切割
- 按大小切割
- 按时间切割
