一、写文件
写文件一般步骤
打开文件,获取文件句柄
os.OpenFile(path, os.O_CREATE, 0666)
我们来了解一下第二个参数的含义:
O_RDONLY // 只读模式打开文件
O_WRONLY // 只写模式打开文件
O_RDWR // 读写模式打开文件
O_APPEND // 写操作时将数据附加到文件尾部
O_CREATE // 如果不存在将创建一个新文件
O_EXCL // 和O_CREATE配合使用,文件必须不存在
O_SYNC // 打开文件用于同步I/O
O_TRUNC // 如果可能,打开时清空文件
第三个参数代表使用指定的模式打开文件
根据不同方法,将数据写入
1. 使用os.File来写文件
三个方法:
-
func (f *File) Write(b []byte) (n int, err error)
Write向文件中写入len(b)字节数据。它返回写入的字节数和可能遇到的任何错误。如果返回值n!=len(b),本方法会返回一个非nil的错误。 -
func (f *File) WriteString(s string) (ret int, err error)
WriteString类似Write,但接受一个字符串参数。 -
func (f *File) WriteAt(b []byte, off int64) (n int, err error)
WriteAt在指定的位置(相对于文件开始位置)写入len(b)字节数据。它返回写入的字节数和可能遇到的任何错误。如果返回值n!=len(b),本方法会返回一个非nil的错误。
// 写个函数,确保文件夹存在,省的重复写
func ensureDirExist(path string) error {
dir := filepath.Dir(path)
exists := isPathExists(dir)
if !exists {
err := os.MkdirAll(dir, os.ModePerm)
if err != nil {
return err
}
}
return nil
}
// 判断路径是否存在
func isPathExists(path string) bool {
if _, err := os.Stat(path); err != nil {
return false
}
return true
}
// 将字符串写入文件
func writeFileWithOsFile(str, path string) error {
// 先验证文件夹是否存在
err := ensureDirExist(path)
if err != nil {
return err
}
// 若文件夹不存在,会出错
f, err := os.OpenFile(path, os.O_APPEND | os.O_CREATE | os.O_WRONLY, 0666)
if err != nil {
return err
}
defer f.Close()
_, err = f.Write([]byte(str))
if err != nil {
return err
}
_, err = f.WriteString(str)
if err != nil {
return err
}
// 获取文件相关信息
fileInfo, err := f.Stat()
if err != nil {
return err
}
fmt.Println(fileInfo.Size())
_, err = f.WriteAt([]byte(str), fileInfo.Size())
fmt.Println(fileInfo.Size()) // 注意:得到的fileInfo不会更新
return err
}
2.使用bufio来写文件
带缓冲的I/O。主要应用场景(大量的写入,多次进行I/O操作,很耗性能),例如:服务器接收数据,客户端发过来的数据比较少,就几个字节这种。会有很多这种操作,若一直写,会很慢。
func writeFileWithBufio(str, path string) error {
// 先验证文件夹是否存在
err := ensureDirExist(path)
if err != nil {
return err
}
// 若文件夹不存在,会出错
f, err := os.OpenFile(path, os.O_APPEND | os.O_CREATE | os.O_WRONLY, 0666)
if err != nil {
return err
}
defer f.Close()
writer := bufio.NewWriterSize(f, 1024)
_, err = writer.Write([]byte(str))
if err != nil {
return err
}
_, err = writer.WriteString(str)
if err != nil {
return err
}
//err = writer.Flush()
fmt.Println(writer.Size())
return err
}
3.使用ioutil来写
func writeFileWithIoutil(str, path string) error {
err := ensureDirExist(path)
if err != nil {
return err
}
return ioutil.WriteFile(path, []byte(str), os.ModePerm)
}
ioutil 这个帮助类还挺好用的,可以自己再看看。
例如:创建临时文件
func CreateTempFile() {
buf := "Hello, World"
//在dir目录下创建一个新的、使用prefix为前缀的临时文件,以读写模式打开该文件并返回os.File指针。如果dir是空字符串,TempFile使用默认用于临时文件的目录(参见os.TempDir函数)。不同程序同时调用该函数会创建不同的临时文件,调用本函数的程序有责任在不需要临时文件时摧毁它。
file, err := ioutil.TempFile("", "tmpfile")
if err != nil {
panic(err)
}
defer func() {
file.Close()
// 一般来说,临时文件不用了,需要移除
err := os.Remove(file.Name())
if err != nil {
log.Fatal(err.Error())
}
}()
if _, err := file.Write([]byte(buf)); err != nil {
panic(err)
}
fmt.Println(file.Name()) // C:\Users\aaa\AppData\Local\Temp\tmpfile741822103
}
4.使用io包中的WriteString方法
func writeFileWithIo(str, path string) error {
// 先验证文件夹是否存在
err := ensureDirExist(path)
if err != nil {
return err
}
// 若文件夹不存在,会出错
f, err := os.OpenFile(path, os.O_APPEND | os.O_CREATE | os.O_WRONLY, 0666)
if err != nil {
return err
}
defer f.Close()
_, err = io.WriteString(f, str)
return err
}
关闭文件句柄
使用完之后,需要将文件关闭,一般在defer中处理
f, err := os.Open("F:/a.txt")
if err != nil {
log.Fatal(err)
return
}
defer f.Close()