操作目录
创建目录
- Mkdir:创建单个目录
- MkdirAll:创建多级目录
func main() {err := os.Mkdir("/Users/itzhuzhu/Desktop/笔记/英语/a", os.ModePerm)if err != nil {fmt.Println("创建失败", err)} else {fmt.Println("创建成功")}err = os.MkdirAll("/Users/itzhuzhu/Desktop/笔记/英语/a/b/c", os.ModePerm)if err != nil {fmt.Println("创建失败", err)} else {fmt.Println("创建成功")}
}
删除文件或目录
- Remove:删除文件或空目录
- RemoveAll:删除文件或目录(包含所有子目录)
func main() {str := "/Users/itzhuzhu/Desktop/NewTest.txt"err := os.Remove(str)if err != nil {fmt.Println("删除失败", err)} else {fmt.Println("删除成功")}str2 := "/Users/itzhuzhu/Desktop/笔记/a"err = os.RemoveAll(str2)if err != nil {fmt.Println("删除失败", err)} else {fmt.Println("删除成功")}
}
Create创建文件:
os.Create:文件不存在则创建,存在则删除文件中的内容
语法:
file:创建文件的指针
err:创建文件出现异常后的信息file, err := os.Create("创建文件存放的路径")
演示:
func main() {file, err := os.Create("/Users/itzhuzhu/Desktop/笔记/test.txt")if err != nil {fmt.Println("创建失败 ", err)} else {fmt.Println("创建成功")}defer file.Close() // 关流(不关流会长时间占用内存)
}
写入数据:
Write写数据:
func main() {file, err := os.Create("/Users/itzhuzhu/Desktop/笔记/test.txt")if err != nil {fmt.Println("创建失败", err)}// 返回值参数1是写的字符长度,参数2是异常信息str := "我是写进去的数据"len, err := file.Write([]byte(str)) //将字符串转换成字节切片if err != nil {fmt.Println("写入失败", err)} else {fmt.Println("写入成功,写入长度为:", len, "字节")}defer file.Close()
}
WriteString写数据:
WriteString底层也是调用的Write,但是Write需要转换字节数组,比较麻烦,WriteString不需要手动转换,比较方便
func main() {file, err := os.Create("/Users/itzhuzhu/Desktop/笔记/test.txt")if err != nil {fmt.Println("创建失败", err)}str := "我是写进去的数据"len, err := file.WriteString(str)if err != nil {fmt.Println("写入失败", err)} else {fmt.Println("写入成功,写入长度为:", len, "字节")}defer file.Close()
}
WriteAt写数据:在指定的位置写入数据
func main() {file, err := os.Create("/Users/itzhuzhu/Desktop/笔记/test.txt")if err != nil {fmt.Println("创建失败", err)}defer file.Close()str := "WriteAt写入的数据"/*参数1:在原数据后要加的空格数参数2:将数据追加到源文件末尾返回值1:返回文件中原数据的长度,如参数1为非0,也会算做源文件长度,是先加上空格再计算的返回值2:错误信息*/num, err := file.Seek(0, io.SeekEnd)fmt.Println("写入数据前的长度为:", num)/*参数1:要写的数据参数2:是要写入数据的开始索引,上面引用了io.SeekEnd可以计算出原数据的长度,然后就可以在原数据基础上追加数据,如果写0会从0索引覆盖原数据返回值1:写入的字符长度返回值2:异常信息*/len, err := file.WriteAt([]byte(str), num)if err != nil {fmt.Println(err)}fmt.Println("写入后的长度为:", len)
}
OpenFile追加数据:
文件里已经有数据的情况下,用上面的三种方式去写,会出现覆盖的效果,WriteAt可以指定索引,但是比较麻烦, os.OpenFile()可以打开已有文件进行操作
OpenFile有三个参数:
- 参数1:打开文件的路径
- 参数2:模式,常见的模式有
参数 | 说明 |
---|---|
O_RDONLY | 只读方式打开 |
O_WRONLY | 只写方式打开 |
O_RDWR | 读写方式打开 |
O_APPEND | 追加方式打开 |
O_CREATE | 不存在,则创建 |
O_EXCL | 如果文件存在,且标定了O_CREATE的话,则产生一个错误 |
O_TRUNC | 如果文件存在,且它成功地被打开为只写或读写方式,将其长度裁剪唯一(覆盖) |
O_NOCTTY | 如果文件名代表一个终端设备,则不把该设备设为调用进程的控制设备 |
O_NONBLOCK | 如果文件名代表一个FIFO,或一个块设备,字符设备文件,则在以后的文件及I/O操作中置为非阻塞模式 |
O_SYNC | 当进行一系列写操作时,每次都要等待上次的I/O操作完成再进行 |
- 参数3:表示权限,取值范围(0-7),和linux里操作文件那个权限一样
0:没有任何权限
1:执行权限(如果是可执行文件,是可以运行的)
2:写权限
3:写权限与执行权限
4:读权限
5:读权限与执行权限
6:读权限与写权限
7:读权限,写权限,执行权限
演示:
func main() {file, err := os.OpenFile("/Users/itzhuzhu/Desktop/笔记/test.txt", os.O_APPEND, 6)if err != nil {fmt.Println("打开失败", err)}defer file.Close()len, err := file.WriteString("我追加了吗")if err != nil {fmt.Println("追加失败", err)}fmt.Println("追加后数据的长度为:", len)
}
输出:原因是OpenFile第二个参数只有读和写的权限,还有有一个打开的权限
追加失败 write /Users/itzhuzhu/Desktop/笔记/Golang/Golang延迟调用defer.md: bad file descriptor
追加后数据的长度为: 0
修改后:
func main() {file, err := os.OpenFile("/Users/itzhuzhu/Desktop/笔记/test.txt", os.O_APPEND|os.O_WRONLY, 6)if err != nil {fmt.Println("打开失败", err)}defer file.Close()len, err := file.WriteString("我追加了吗")if err != nil {fmt.Println("追加失败", err)}fmt.Println("追加后数据的长度为:", len)
}
Open读取文件数据:
Open底层调用的是OpenFile方法,但是参数是写死了(只读模式),源码如下
func Open(name string) (*File, error) {return OpenFile(name, O_RDONLY, 0)
}
演示:
func main() {// 追加写数据file, err := os.Open("/Users/itzhuzhu/Desktop/笔记/test.txt")if err != nil {fmt.Println(err)}defer file.Close()// 读数据,定义一个切片存储文件读取的数据buffer := make([]byte, 1024)len, err := file.Read(buffer) // len:读取文件中的数据长度if err != nil {fmt.Println(err)}fmt.Println("读取数据的长度为:", len)//fmt.Println(buffer) // 直接打印都是数字(ascii码值)fmt.Println("内容为:", string(buffer)) // 将类型转换为string,可以展示出内容fmt.Println("内容为:", string(buffer[:len])) //初始化切片的长度是1024,数据没满的时候就会用默认值0代替,可以使用切片截取操作
}
ReadBytes缓冲区读取:
在使用ReadBytes( )函数读取数据时,需要用到缓冲区,所谓缓冲区就是存储数据的区域,也就是先将从文件中读取的数据存储在该区域内,然后在将区域中的数据取出来,写到磁盘上。
提供缓冲区的原因是:
为了缓和 CPU 与 磁盘设备之间速度不匹配矛盾。文件缓冲区是用以暂时存放读写期间的文件数据而在内存区预留的一定空间。
演示:
func main() {// 追加写数据file, err := os.Open("/Users/itzhuzhu/Desktop/filetest/OpenFileTest.txt")if err != nil {fmt.Println(err)}defer file.Close()// 读数据,定义一个切片存储文件读取的数据r := bufio.NewReader(file)for {buf, err := r.ReadBytes('\n')if err == io.EOF { // io.EOF表示读取到文件末尾break}fmt.Println(err)fmt.Println("buf", string(buf))}
}
Stat
查看文件属性
type FileInfo interface {Name() string // 文件名称Size() int64 // 文件大小(字节)Mode() FileMode // 权限ModTime() time.Time // 修改时间IsDir() bool // 是否为目录Sys() any // 底层数据源,不知道这是干嘛的
}
演示:
func main() {path := "/Users/itzhuzhu/Desktop/笔记/test.txt"stat, _ := os.Stat(path)fmt.Println("文件名称:", stat.Name())fmt.Println("文件大小:", stat.Size(), "字节")fmt.Println("当前权限:", stat.Mode())fmt.Println("修改时间:", stat.ModTime())fmt.Println("是否为目录:", stat.IsDir())fmt.Println("底层数据源:", stat.Sys())
}
IsNotExist
判断文件是否存在
func main() {_, err := os.Stat("/Users/itzhuzhu/Desktop/笔记/test.txt")if os.IsNotExist(err) {fmt.Println("文件不存在")} else {fmt.Println("文件存在")}
}
Copy
func main() {// 打开原数据文件oldFile, err := os.Open("/Users/itzhuzhu/Desktop/笔记/test.txt")if err != nil {fmt.Println("打开源文件失败", err)}defer oldFile.Close()// 打开新文件newFile, err := os.OpenFile("/Users/itzhuzhu/Desktop/笔记/NewTest.txt", os.O_RDWR|os.O_CREATE, 0777)if err != nil {fmt.Println("打开新文件失败", err)}defer newFile.Close()written, err := io.Copy(newFile, oldFile)if err != nil {fmt.Println("复制失败", err)} else {fmt.Println("复制成功,共", written, "字节")}
}