io
golang中 os.File 库封装了文件相关操作,File是一个结构体。
go语言标准库文档:https://studygolang.com/static/pkgdoc/pkg/os.htm#File
具体的使用:
1、打开文件
1)os.Open
//Open打开一个文件用于读取。
//如果操作成功,返回的文件对象的方法可用于读取数据;对应的文件描述符具有O_RDONLY模式。
//如果出错,错误底层类型是*PathError。
func Open(name string) (file *File, err error)
1.1 os.Create 创建文件
f,err := os.Create( fileName ) defer f.Close() if err !=nil { fmt.Println( err.Error() ) } else { _,err=f.Write([]byte("要写入的文本内容")) fmt.Println( err.Error() ) }
// 向文件写入字节数据 func (f *File) Write(b []byte) (n int, err error) //
向文件写入字符串 func (f *File) WriteString(s string) (ret int, err error)
2)os.OpenFile
OpenFile是一个更一般性的文件打开函数,大多数调用者都应用Open或Create代替本函数。它会使用指定的选项(如O_RDONLY等)、指定的模式(如0666等)打开指定名称的文件。如果操作成功,返回的文件对象可用于I/O。如果出错,错误底层类型是*PathError。
func OpenFile(name string, flag int, perm FileMode) (file *File, err error)
① 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 // 如果可能,打开时清空文件 !!!谨慎使用!!! )
② FileMode参数代表文件的模式和权限位,主要使用在Linux和Unix系统下,windows系统下无效。
const ( // 单字符是被String方法用于格式化的属性缩写。 ModeDir FileMode = 1 << (32 - 1 - iota) // d: 目录 ModeAppend // a: 只能写入,且只能写入到末尾 ModeExclusive // l: 用于执行 ModeTemporary // T: 临时文件(非备份文件) ModeSymlink // L: 符号链接(不是快捷方式文件) ModeDevice // D: 设备 ModeNamedPipe // p: 命名管道(FIFO) ModeSocket // S: Unix域socket ModeSetuid // u: 表示文件具有其创建者用户id权限 ModeSetgid // g: 表示文件具有其创建者组id的权限 ModeCharDevice // c: 字符设备,需已设置ModeDevice ModeSticky // t: 只有root/创建者能删除/移动文件 // 覆盖所有类型位(用于通过&获取类型位),对普通文件,所有这些位都不应被设置 ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice ModePerm FileMode = 0777 // 覆盖所有Unix权限位(用于通过&获取类型位) )
2、关闭文件//Close关闭文件f,使文件不能用于读写。它返回可能出现的错误。
func (f *File) Close() error
//打开文件 file, err := os.Open("test.txt") if err != nil { fmt.Println("open file err=", err) } fmt.Printf("file=%v", file) //这里打印出 file=&{0xc00007a780} ,因为file是一个指针 //关闭文件file,要及时关闭文件句柄file,防止内存泄漏 defer file.Close()
//关闭文件file,要及时关闭文件句柄file,防止内存泄漏
defer file.Close()
3、读取文件
1)读取到file中,再利用ioutil将file直接读取到[]byte中
# 例子:
func Read1() string { f, err := os.Open("./test.txt") if err != nil { fmt.Println("read file fail", err) return "" } defer f.Close() fd, err := ioutil.ReadAll(f) if err != nil { fmt.Println("read to fd fail", err) return "" } return string(fd) }
2)io/ioutil包中的ReadFile方法一次性读取,适用于文件不大的情况下。
这种方式下文件的Open和Close被封装到ReadFile函数内部,直接读取即可。
# 例子:
func Read2() string {
f, err := ioutil.ReadFile("./test.txt")
if err != nil {
fmt.Println("read fail", err)
}
return string(f)
}
3)使用带缓冲区的方式
func Read3() string { file, err := os.Open("./basic/type/test.txt") if err != nil { fmt.Println("open file err=", err) } defer file.Close() var f string //创建一个 *Reader,带缓冲区的 //默认缓冲区为defaultBufSize = 4096 reader := bufio.NewReader(file) //循环读取文件内容 for { str, err := reader.ReadString('\n') f += str if err == io.EOF { //io.EOF表示文件的末尾 break } } return f }
经验证,上面的'\n' 对windows换行和linux都适用。
reader还有一个ReadLine的方法,不过是低阶api,上层封装是 ReadBytes('\n') or ReadString('\n').
ReadLine is a low-level line-reading primitive. Most callers should use ReadBytes('\n') or ReadString('\n') instead or use a Scanner
问题:为什么
if err == io.EOF { /
要放在后面。因为读取到最后一行(这行还有内容),这行返回的str有内容,但是err是EOF.
ReadString("\n")应该是读到\n或EOF时返回,所以最后一行会返回EOF,但是你的代码中判断EOF后直接break了,此时line就是最后一行的内容
4、写入文件
func write1() { filePath := "./basic/type/test1.txt" file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666) if err != nil { fmt.Printf("open file err = %v\n", err) return } defer file.Close() //写入文件 str := "hello world\r\n" writer := bufio.NewWriter(file) for i := 0; i < 5; i++ { writer.WriteString(str) } //writer是带缓存的,因此在调用writerString方法时,其实内存是先写入缓存的 //Flush方法将缓存的数据真正写入文件中 writer.Flush() }
————————————————
参考链接:https://blog.csdn.net/lff1123/article/details/122747038
https://blog.csdn.net/weixin_37717557/article/details/106532544