1. 常用方法和函数
## os 模块1. File结构体Syntax: type File struct { }Man: 文件对象2. Open()Syntax: func Open(name string) (file *File, err error)Man: Open打开一个文件用于读取,对应的文件描述符具有O_RDONLY模式3. OpenFile()Syntax: func OpenFile(name string, flag int, perm FileMode) (file *File, err error)Man: 打开文件,可以指定打开方式、权限等。一般应用于写文件的场景flag使用位运算中的 | 拼接: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/OO_TRUNC int = syscall.O_TRUNC // 如果可能,打开时清空文件)perm是Linux下文件权限,如 0644, 0400 等3. Close()Syntax: func (f *File) Close() errorMan: Close关闭文件f,使文件不能用于读写。它返回可能出现的错误。4. Name()Syntax: func (f *File) Name() stringMan: Name方法返回(提供给Open/Create等方法的)文件名称## bufio模块1. Reader结构体Syntax: type Reader struct { }Man: Reader实现了给一个io.Reader接口对象附加缓冲2. NewReader()Syntax: func NewReader(rd io.Reader) *ReaderMan: 创建默认缓冲区大小的 Reader 对象指针,默认为 20483. NewReaderSize()Syntax: func NewReaderSize(rd io.Reader, size int) *ReaderMan: 创建指定缓冲区大小的 Reader 对象指针4. ReadString()Syntax: func (b *Reader) ReadString(delim byte) (line string, err error)Man: ReadString读取直到第一次遇到delim字节,返回一个包含已读取的数据和delim字节的字符串。如果ReadString方法在读取到delim之前遇到了错误,它会返回在错误之前读取的数据以及该错误(一般是io.EOF)。当且仅当ReadString方法返回的切片不以delim结尾时,会返回一个非nil的错误。5. ReadBytes()Syntax: func (b *Reader) ReadBytes(delim byte) (line []byte, err error)Man: ReadBytes读取直到第一次遇到delim字节,返回一个包含已读取的数据和delim字节的切片。如果ReadBytes方法在读取到delim之前遇到了错误,它会返回在错误之前读取的数据以及该错误(一般是io.EOF)。当且仅当ReadBytes方法返回的切片不以delim结尾时,会返回一个非nil的错误。6. NewWriter()Syntax: func NewWriter(w io.Writer) *WriterMan: NewWriter创建一个具有默认大小缓冲、写入w的*Writer7. NewWriterSize()Syntax: func NewWriterSize(w io.Writer, size int) *WriterMan: NewWriterSize创建一个具有最少有size尺寸的缓冲、写入w的*Writer。8. WriteString()Syntax:func (b *Writer) WriteString(s string) (int, error)Man: WriteString写入一个字符串,返回写入的字节数。9. Write()Syntax: func (b *Writer) Write(p []byte) (nn int, err error)Man: Write将p的内容写入缓冲。返回写入的字节数。如果返回值nn < len(p),还会返回一个错误说明原因。10. Flush()Syntax: func (b *Writer) Flush() errorMan: 刷盘,将系统缓冲区内容写入文件## ioutil模块1. ReadFile()Syntax: func ReadFile(filename string) ([]byte, error)Man: ReadFile 从filename指定的文件中读取数据并返回文件的内容。成功的调用返回的err为nil而非EOF2. WriteFile()Syntax: func WriteFile(filename string, data []byte, perm os.FileMode) errorMan: 函数向filename指定的文件中写入数据。如果文件不存在将按给出的权限创建文件,否则在写入数据之前清空文件。
2. 读文件
2.1. 带缓冲区的方式读取文件
使用缓冲区的方式读取文件内容,适合文件较大的情况或者文件大小未知的情况,避免一次性占用太多内存。
package mainimport ("bufio""fmt""io""os")func main() {file, err := os.Open("/etc/passwd")if err != nil {fmt.Printf("读取文件失败,err: %v\n", err)return}defer file.Close()// 使用缓冲区的方式读取文件内容,适合文件内容较大的情况,避免一次性占用太多内存reader := bufio.NewReaderSize(file, 2048)for {str, err := reader.ReadString('\n')if err == io.EOF {break} else if err != nil {fmt.Println("文件读取异常,err=", err)} else {fmt.Print(str)}}}
2.2. 一次性读取文件内容
一次性读取文件内容,适合小文件,如配置文件等。
package mainimport ("fmt""io/ioutil")func main() {// 一次性读取文件内容,适合小文件,如配置文件等if content, err := ioutil.ReadFile("/etc/passwd"); err != nil {fmt.Println("文件读取失败")} else {fmt.Print(string(content))}}
3. 写文件
3.1. 带缓冲的方式写文件
使用带缓冲的方式写文件实际运用场景比较多,需要注意的以下问题:
- 必须要关闭文件前使用
writer.Flush(),否则可能导致写入的文件内容不全 - 写入字节切片
[]byte和string是一样的效果,不会出现中文乱码问题 - 在Linux下,如果当前用户对文件没有写入权限如0400权限下,会提示
permission denied - 写文件时是覆盖还是追加,取决于打开文件时使用的 flag
3.1.1. 追加文件内容
```go package main
import ( “bufio” “fmt” “os” )
func main() { file, err := os.OpenFile(“test.txt”, os.OWRONLY | os.O_CREATE | os.O_APPEND, 0600) if err != nil { fmt.Println(“打开文件失败; err=”,err) return } defer func() { = file.Close() }() // 使用缓冲的方式写字符串到文件 writer := bufio.NewWriter(file) for i:=0; i<3; i++ { if , err := writer.WriteString(“Hello 北京”+”\n”); err != nil { fmt.Println(“文件写入失败, err=”, err) break } } // 使用缓冲的方式写byte切片到文件 sli := []byte(“Hello 北京\n”) for i:=0; i< 3; i++ { if , err := writer.Write(sli); err != nil { fmt.Println(“文件写入失败, err=”, err) break } } _ = writer.Flush() }
<a name="yK6iF"></a>#### 3.1.1. 覆盖文件内容想要覆盖文件,必须要添加 `os.O_TRUNC` ,否则会和原有内容重叠。```gopackage mainimport ("bufio""fmt""os")func main() {file, err := os.OpenFile("test.txt", os.O_WRONLY | os.O_CREATE | os.O_TRUNC, 0600)if err != nil {fmt.Println("打开文件失败; err=",err)return}defer func() {_ = file.Close()}()for i:=0; i<3; i++ {if _, err := writer.WriteString("Hello 南京"+"\n"); err != nil {fmt.Println("文件写入失败, err=", err)break}}_ = writer.Flush()}
3.2. 一次性写文件
一次性写入文件内容,比如调用go生成k8s的清单文件等。
package mainimport ("fmt""io/ioutil")func main() {err := ioutil.WriteFile("go.txt", []byte("Golang 不难!"), 0400)if err != nil {fmt.Println("文件写入失败,err=", err)}}
3.3. 判断文件是否存在并写入
在下面的案例中,由于涉及 ssh-key,因此覆写时,需要修改文件权限,避免写入失败!
package mainimport ("fmt""io/ioutil""os")func FileIsExist(filename string) (bool, error) {if _, err := os.Stat(filename); err == nil {_ = os.Chmod("go.txt", 0600)return true, nil} else if os.IsNotExist(err) {return false, nil} else {return false, err}}func main() {if flag, _ := FileIsExist("go.txt"); ! flag {fmt.Println("文件不存在")return}if err := ioutil.WriteFile("go.txt", []byte("ssh-key"), 0400); err != nil {fmt.Println("文件写入失败,err=",err)}}
