文件操作
os
包提供了平台无关的操作系统功能接口。尽管错误处理是 go 风格的,但设计是 Unix 风格的;所以,失败的调用会返回 error
而非错误码。通常 error
里会包含更多信息。例如,如果使用一个文件名的调用(如 Open、Stat)失败了,打印错误时会包含该文件名,错误类型将为 *PathError
,其内部可以解包获得更多信息。
os 包规定为所有操作系统实现的接口都是一致的。有一些某个系统特定的功能,需要使用 syscall
获取。实际上,os
依赖于 syscall
。在实际编程中,我们应该总是优先使用 os
中提供的功能,而不是 syscall
。
带缓冲读取
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func main() {
file, err := os.Open("/Users/yangsx/Desktop/helloworld.txt") // 返回一个文件对象/文件指针/文件句柄
defer file.Close() // 关闭File句柄
if err != nil {
fmt.Println("open file err: ", err)
}
// 创建一个*Reader,默认带大小4096字节的缓冲区
reader := bufio.NewReader(file)
// 循环读取文件内容
for {
str, err := reader.ReadString('\n') // 读取到换行符就结束
if err == io.EOF { // 如果读取到文件末尾
break
}
// 输出该行
fmt.Print(str) // 会把换行符打印
}
fmt.Println("----文件读取结束----")
}
一次全文读取
1.16后,
ioutil
实际上调用os.ReadFile()
函数,推荐直接使用os.ReadFile()
函数
package main
import (
"fmt"
"io/ioutil"
)
func main() {
// 返回字节数组
bs, err := ioutil.ReadFile("/Users/yangsx/Desktop/helloworld.txt")
if err != nil {
fmt.Println("读取文件失败:", err)
}
fmt.Printf("%s", bs)
}
打开文件的方式
使用func OpenFile(name string, flag int, perm FileMode) (file *File, err error)
函数打开文件并指定打开模式:
// flag,打开方式,多个可以组合使用 os.O_RDWR | os.APPEND
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 // 如果可能,打开时清空文件
)
// 文件权限
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权限位(用于通过&获取类型位)
)
一次性写入
实际调用
os.WriteFile()
函数
package main
import (
"fmt"
"io/ioutil"
"log"
)
func main() {
str := "hello"
// 覆盖写入一次性写入字符串
err := ioutil.WriteFile("/Users/yangsx/Desktop/helloworld.txt", []byte(str), 0666)
if err != nil {
log.Fatalln(err)
}
fmt.Println("写入成功")
}
带缓冲追加写入
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
file, err := os.OpenFile("/Users/yangsx/Desktop/helloworld.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
defer file.Close()
if err != nil {
fmt.Println("打开文件出错:", err)
}
// 写入数据
str := "你好,世界\n"
// 使用带缓存的 *Writer
writer := bufio.NewWriter(file)
for i := 0; i < 5; i++ {
writer.WriteString(str)
}
// 因为writer是带缓存的,需要使用flush函数真正写入到磁盘中
writer.Flush()
fmt.Println("写入数据成功")
}
覆盖写入
使用选项, os.O_TRUNC
清空文件
判断文件状态
判断文件/文件夹是否存在:
// Stat函数就像linux下的stat命令,该函数会返回一个FileInfo struct
func PathExist(path string) (bool, error){
_, err := os.Stat(path)
if err == nil {
return true, nil // 没有错误,说明文件/文件夹一定存在
}
if os.IsNotExist(err) { // 如果错误信息是文件不存在,则说明文件/文件夹一定不存在
return false, nil
}
return false, err
}
获取文件状态:
package main
import (
"fmt"
"log"
"os"
)
func main() {
fi, err := os.Stat("/Users/yangsx/Desktop/helloworld.txt")
if err != nil {
log.Fatalln(err)
}
fmt.Printf(`文件名称为:%s,
文件大小为: %d,
是否是文件夹: %t,
文件的Mode: %d
`, fi.Name(), fi.Size(), fi.IsDir(), fi.Mode())
}
文件拷贝
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func main() {
src := "/Users/yangsx/Desktop/helloworld.txt"
dst := "/Users/yangsx/Desktop/h.txt"
srcF, err := os.OpenFile(src, os.O_RDONLY, 0666)
defer srcF.Close()
if err != nil {
fmt.Println("打开src失败: ", err)
return
}
dstF, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
defer dstF.Close()
if err != nil {
fmt.Println("打开dst失败: ", err)
return
}
// 构建reader 和 writter
reader := bufio.NewReader(srcF)
writer := bufio.NewWriter(dstF)
// 调用拷贝方法
wi, err := io.Copy(writer, reader)
if err != nil {
fmt.Println("拷贝失败 ", err)
return
}
fmt.Println("拷贝成功,字节数:", wi)
}
最后更新于
这有帮助吗?