# 写文件
Go 语言中读写文件还是很方便的,但是有一些点还是需要注意
package main | |
import ( | |
"fmt" | |
"os" | |
"time" | |
) | |
func main() { | |
f, err := os.OpenFile("test",os.O_CREATE|os.O_RDWR|os.O_APPEND, 0777) | |
if err != nil { | |
fmt.Println("error") | |
} | |
// s := []byte("hello world") | |
_, err2 := f.WriteString("hello world! "+time.Now().String()+"\n") | |
if err2 != nil{ | |
fmt.Println("error2") | |
} | |
defer f.Close() | |
} |
打开文件有 Open
和 OpenFile
两个 API,但是 OPEN
返回只读的文件句柄,而 OpenFile
可以自定义权限
const ( | |
// Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified. | |
O_RDONLY int = syscall.O_RDONLY // open the file read-only. | |
O_WRONLY int = syscall.O_WRONLY // open the file write-only. | |
O_RDWR int = syscall.O_RDWR // open the file read-write. | |
// The remaining values may be or'ed in to control behavior. | |
O_APPEND int = syscall.O_APPEND // append data to the file when writing. | |
O_CREATE int = syscall.O_CREAT // create a new file if none exists. | |
O_EXCL int = syscall.O_EXCL // used with O_CREATE, file must not exist. | |
O_SYNC int = syscall.O_SYNC // open for synchronous I/O. | |
O_TRUNC int = syscall.O_TRUNC // truncate regular writable file when opened. | |
) |
O_RDWD
就是读写, O_APPEND
代表以 Append 方式写, O_Create
如果没有文件就创建一个文件。
golang 里写文件如果不是 append 方式的话,那么写文件方式是以写覆盖方式进行的,而不是把文件清空,这点和 python
有一些区别。
如果要清空文件只需要加上 O_TRUNC,
# 按行读取文件
package main | |
import ( | |
"bufio" | |
"fmt" | |
"io" | |
"os" | |
) | |
func main() { | |
f, err := os.OpenFile("test", os.O_CREATE|os.O_RDWR, 0777) | |
if err != nil { | |
fmt.Println("error") | |
} | |
i := 0 | |
reader := bufio.NewReader(f) | |
for { | |
s, err3 := reader.ReadString('\n') | |
if err3 == io.EOF { | |
fmt.Println("end") | |
break | |
} | |
fmt.Printf("s: %v\n", s) | |
fmt.Printf("i: %v\n", i) | |
i++ | |
} | |
defer f.Close() | |
} |
这个以 \n
作为分隔符进行读取,原来文件:
这个读取方式不会把最后那个换行读取过去。
# 直接读
b, err2 := ioutil.ReadFile("test") | |
if err2 != nil{ | |
fmt.Println("err") | |
} | |
all_content := strings.Split(string(b),"\n") | |
for _, v := range all_content { | |
if v==""{ | |
continue | |
} | |
fmt.Printf("v: %v\n", v) | |
} |
一次性把所有内容读到内存,然后用 split
对 string 做切分,注意!
split
对下面累啦,按 \n
进行切分时:
a\nb\nc\n
它实际上返回了 ["a", "b","c", ""]
最后会有一个空字符。
# 按字节数读
f, _ := os.Open("a.txt") | |
for { | |
buf := make([]byte, 6) | |
n, err := f.Read(buf) | |
fmt.Println(string(buf)) | |
fmt.Printf("n: %v\n", n) | |
if err == io.EOF { | |
break | |
} | |
} | |
f.Close() |
定义定义一个 buf 大小
os 包还可以做很多,比如对进程进行操作:
golang 标准库 os 包进程相关操作
# 常用的几个 IO 包
ioutil
bufio
os
io
io
包定义了 reader
和 writer
两个接口,也就说只要实现了这个接口就可以被这些 io 包调用。
比如, ioutil.ReadAll 的接口
func ReadAll(r io.Reader) ([]byte, error)
那么 string.Reader
可以被调用,同时 os.file
也就说 os.Openfile
返回的句柄也可以调用这个 readall
# ioutil
func ReadAll(r io.Reader) ([]byte, error) |
func ReadDir(dirname string) ([]fs.FileInfo, error) |
func ReadFile(filename string) ([]byte, error) |
func TempDir(dir, pattern string) (name string, err error) |
这个 TempDir,如果 pattern 中有 *
这个符号,比如 *-logs
这个作为传入的 pattern,那么会生成诸如 238493589-logs
这样一个临时的文件夹,前面数字是随机的,它会取代 *
所在位置。
即使没加 defer os.removeall 它也会自动删除的。
func WriteFile(filename string, data []byte, perm fs.FileMode) error |
如果没有文件就创建,如果有文件就清空写,默认使用 truncate
参数。
Flush
用于刷新缓冲区。
# Stdin 和 stdout
这个要查直接看 fmt
文档就行了
要记住的要, %q
输出字符串字面值,比如 hello\nworld