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/O
O_TRUNC int = syscall.O_TRUNC // 如果可能,打开时清空文件
)
perm是Linux下文件权限,如 0644, 0400 等
3. Close()
Syntax: func (f *File) Close() error
Man: Close关闭文件f,使文件不能用于读写。它返回可能出现的错误。
4. Name()
Syntax: func (f *File) Name() string
Man: Name方法返回(提供给Open/Create等方法的)文件名称
## bufio模块
1. Reader结构体
Syntax: type Reader struct { }
Man: Reader实现了给一个io.Reader接口对象附加缓冲
2. NewReader()
Syntax: func NewReader(rd io.Reader) *Reader
Man: 创建默认缓冲区大小的 Reader 对象指针,默认为 2048
3. NewReaderSize()
Syntax: func NewReaderSize(rd io.Reader, size int) *Reader
Man: 创建指定缓冲区大小的 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) *Writer
Man: NewWriter创建一个具有默认大小缓冲、写入w的*Writer
7. NewWriterSize()
Syntax: func NewWriterSize(w io.Writer, size int) *Writer
Man: 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() error
Man: 刷盘,将系统缓冲区内容写入文件
## ioutil模块
1. ReadFile()
Syntax: func ReadFile(filename string) ([]byte, error)
Man: ReadFile 从filename指定的文件中读取数据并返回文件的内容。成功的调用返回的err为nil而非EOF
2. WriteFile()
Syntax: func WriteFile(filename string, data []byte, perm os.FileMode) error
Man: 函数向filename指定的文件中写入数据。
如果文件不存在将按给出的权限创建文件,否则在写入数据之前清空文件。
2. 读文件
2.1. 带缓冲区的方式读取文件
使用缓冲区的方式读取文件内容,适合文件较大的情况或者文件大小未知的情况,避免一次性占用太多内存。
package main
import (
"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 main
import (
"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` ,否则会和原有内容重叠。
```go
package main
import (
"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 main
import (
"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 main
import (
"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)
}
}