这是我参与【第五届青训营】伴学笔记创作活动的第六天,此篇概述一下在青训营学习的go文件管理相关的知识。
文件基础
文件的基本操作
fileInfo, err := os.Stat("") // 文件传入
if err != nil {
fmt.Println("err: ", err)
return
}
// 常用直接调用的函数
fileInfo.Name() // 文件名
fileInfo.Size() // 文件大小
fileInfo.Mode() // 文件权限
fileInfo.ModTime()// 修改时间
fileInfo.IsDir() // 是否文件夹
fileInfo.Sys() // 基础数据源接口
文件的权限
r,w,x; 004,002,001分别表示读,写,执行
- 符号表示: -xr, -x, -rwxr
- 八进制表示: 0755, 0555, 0444, 0666
文件操作
-
路径:绝对路径,相对路径
-
创建目录
// 获取父目录 path.Join(filepath, "..") // 创建一层目录 err := os.Mkdir(filepath, os.ModePerm) if err != nil { fmt.Println("err: ", err) return } fmt.Println("文件夹创建成功") // 创建多层目录 os.MkdirAll(filepath, os.ModePerm) -
创建文件:file, err := os.Create(filepath)
-
打开文件
file, err := os.Open(filepath) // 只读模式 file, err := os.OpenFile(filepath, mode) // mode 表示读写模式或权限等,如 os.O_RDONLY 或 os.O_CREATE -
关闭文件:os.Close()
-
删除文件或空目录:os.Remove()
-
删除所有:os.RemoveAll()
I/O操作
I/O包
-
Reader 接口
// 基础的文件读取操作 // step1: file, err := os.Open(filename) if err != nil { fmt.Println("err: ", err) return } // step2: defer file.Close() // step3: bs := make([]byte, 4, 4) n, err := file.Read(bs) n-> 长度 bs-> 字节 fmt.Println(string(bs)) -
Writer 接口
// 基础文件写操作 bs := []byte{65,66,67,68,69,70} n, err := file.Write(bs) // 直接写字符串 file.WriteString("HelloWorld") file.Write([]byte("today"))
文件复制
// 用 read 和 write 实现函数
func CopyFile(srcFile, dest) {
file1, err := os.Open(srcFile) // 原文件夹
if err != nil {
return 0, err
}
file2, err := os.OpenFile(destFile, os.O_WRONLY|os.O_CREATE, os.ModePerm)
// 目标文件夹
if err != nil {
return 0, err
}
defer file1.Close()
defer file2.Close()
// 读写
bs := make([]byte, 1024, 1024)
n := -1 // 读取的数据量
total := 0
for {
n, err = file1.Read(bs)
if err == io.EOF || n == 0 { // 碰到 EOF 退出循环
fmt.Println("拷贝完成...")
break
}
else if err != nil {
fmt.Println("报错了...")
return total, err
}
total += n
file2.Write(bs[:n]) // 写入数据
}
return total, nil
}
// io 包下的 Copy() 方法
func copyFile2(srcFile, destFile string) (int64,error) {
file1, err := os.Open(srcFile) // 打开源文件夹,准许读操作
if err != nil {
return 0, err
}
// 打开目标文件,准许创建,写操作
file2, err := os.OpenFile(destFile, os.O_WRONLY|os.O_CREATE, os.ModePerm)
if err != nil {
return 0, err
}
defer file1.Close()
defer file2.Close()
return io.Copy(file2, file1) // Copy 函数直接调用
}
// ioutil 包方法 (由于使用一次性读取文件,不适合大文件,容易内存溢出)
func copyFile3(srcFile, destFile string) (int, error) {
bs, err := ioutil.ReadFile(srcFile)
if err != nil {
return 0, err
}
err = ioutil.WriteFile(destFile, bs, 0777)
if err != nil {
return 0, err
}
return len(bs), nil
}
其他方法:CopyN(dest, src, n) 复制 src 中 n 个字节到 dest
CopyBuffer(dest, src, buf) 为指定一个buf 缓冲区, 以这个大小完全复制
断点续传
file.Seek(len, mode)
// len 表示距离
/* mode :
io.SeekStart 光标移到距离开始len的位置
io.SeekCurrent 光标移到距离当前len的位置
io.SeekEnd 光标移到距离结尾len的位置
*/
bufio 包原理
作用:将 io 包下的 Reader, Writer 对象进行包装,带缓存的包装,提高读写效率
input := bufio.NewReader(file/os.Stdin)
scanner := bufio.NewScanner(file/os.Stdin)
具体用法略
ioutil 包
-
data, err := ioutil.ReadFile(filename) 读取文件中的所有数据
-
ioutil.WriteFile(filename, []byte(data), os.ModePerm) 往文件中写入数据
-
str := "hahaha"
newstr := strings.NewReader(str)
data, err := ioutil.ReadAll(newstr) // 将字符串转换为字节流
-
临时目录和临时文件
dir, err := ioutil.TempDir(dirpath, dirnameprefix) // 创建临时目录 file, err := ioutil.TempFile(dir, filenameprefix) // 创建临时文件
便利文件夹
func listFiles(dirname string, level int) {
fileInfos, err := ioutil.ReadDir(dirname) // 读入目录下文件
s := ""
for i := 0; i < level; i++ {
s = " " + s
} // 空格,便于层次化目录结构
if err != nil {
log.Fatal(err)
}
for _, fi := range fileInfos { // 获取文件
filename := dirname + "/" + fi.Name()
fmt.Printf("%s%s\n", s, filename)
if fi.IsDir() {
// 递归调用方法
listFiles(filename)
}
}
}