文件操作案例
import (
"bufio"
"fmt"
"io"
"os"
)
//写入方式一
func main01() {
//路径分为绝对路径和相对路径
//create,文件存在则会覆盖原始内容(其实就相当于清空),不存在则创建
fp, error := os.Create("./a.txt")
if error != nil {
fmt.Println("文件创建失败!")
return
}
//延迟调用,关闭文件
defer fp.Close()
//写入文件,windows上面换行\r\n其他\n即可
fp.WriteString("hello\r\n")
n, _ := fp.WriteString("world\r\n")
fmt.Println(n) //7 其实就是写入的内容长度world\r\n刚好7
}
//写入方式二
func main2() {
fp, error := os.Create("./a.txt")
if error != nil {
fmt.Println("文件创建失败!")
return
}
defer fp.Close()
b := []byte{'h', 'e', 'l', 'l'}
fp.Write(b)
str := "world"
//字符串和切片允许相互转换
b1 := []byte(str)
fp.Write(b1)
}
//写入方式三:指定位置
func main3() {
//os.Open是只读打开
/**
读写方式:
O_APPEND:追加
O_RDONLY: 只读
O_RDWR:可读可写
O_WRONLY:只写
*/
//第三个参数是权限,取值范围0-7
/**
0:没有任何权限
1:执行权限(如果是可执行文件,是可以运行的)
2:写权限
3:写权限与执行权限
4:读权限
5:读权限与执行权限
6:读权限与写权限
7:读权限,写权限,执行权限
*/
//OpenFile无法创建文件
fp, error := os.OpenFile("./a.txt", os.O_RDWR, 6)
if error != nil {
fmt.Println("文件创建失败!")
return
}
defer fp.Close()
//b:=[]byte("hello")
//执行前内容aaaaa
//执行后内容ahello
//fp.WriteAt(b,1)
//获取文件字符个数,参数一可以是负数,这样可以往左偏移
n, _ := fp.Seek(0, io.SeekEnd)
b := []byte("hello")
//此时就相当于追加了,因为n此时是内容总长度了
fp.WriteAt(b, n) //ahellohello
}
//读取文件
func main4() {
fp, error := os.Open("./a.txt")
if error != nil {
/**
系统打开文件个数限制是65535
所以重复打开同一文件是可以的
1. 文件不存在
2. 文件权限
3. 文件打开上限
*/
fmt.Println("文件打开失败!")
return
}
defer fp.Close()
b := make([]byte, 1024)
//n, error := fp.Read(b)
//fmt.Println(n) //n是长度
fp.Read(b)
//也可以通过for遍历读取
fmt.Println(string(b)) //ahellohello
}
func main5() {
fp, error := os.Open("./a.txt")
if error != nil {
fmt.Println("文件打开失败!")
return
}
defer fp.Close()
b := make([]byte, 20)
for {
n, err := fp.Read(b)
//文件结束
if err == io.EOF { //-1
break
}
fmt.Print(string(b[:n]))
}
}
func main() {
fp, error := os.Open("./a.txt")
if error != nil {
fmt.Println("文件打开失败!")
return
}
defer fp.Close()
//行读取。新建缓冲区,把内容先放到缓冲区
r := bufio.NewReader(fp)
for {
buf, err := r.ReadBytes('\n')
fmt.Print(string(buf))
//文件结束,此时必须读取在上面,否则最后一行的时候err == io.EOF,则永远会少读取一行
if err == io.EOF { //-1
break
}
}
}
拷贝文件
func main() {
// 打开读文件
f_r, err := os.Open("C:/z1/测试.avi")
if err != nil {
fmt.Println("Open err: ", err)
return
}
defer f_r.Close()
// 创建写文件
f_w, err := os.Create("C:/z1/test.avi")
if err != nil {
fmt.Println("Create err: ", err)
return
}
defer f_w.Close()
// 从读文件中获取数据,放到缓冲区中。
buf := make([]byte, 4096)
// 循环从读文件中,获取数据,“原封不动的”写到写文件中。
for {
n, err := f_r.Read(buf)
if err != nil && err == io.EOF {
fmt.Printf("读完。n = %d\n", n)
return
}
f_w.Write(buf[:n]) // 读多少,写多少
}
}
目录操作
打开目录
OpenFile:以只读方式打开目录
- 参1:name, 打开目录的路径: 绝对路径、相对路径
- 参2:打开目录权限: O_RDONLY
- 参3:os.ModeDir,
返回值: 返回一个可以读目录的 文件指针。
读目录:Readdir
原型:func (f *File) Readdir(n int) ([]FileInfo, error) {
参数: 欲打开的目录项个数。 -1 , 表所有;例如10,则只读取十个目录项
返回值: FileInfo :
type FileInfo interface {
Name() string // base name of the file
Size() int64 // length in bytes for regular files; system-dependent for others
Mode() FileMode // file mode bits
ModTime() time.Time // modification time
IsDir() bool // abbreviation for Mode().IsDir()
Sys() interface{} // underlying data source (can return nil)
}
代码案例
func main() {
// 获取用户输入的目录路径
fmt.Println("请输入待查询的目录:")
var path string
fmt.Scan(&path)
// 打开目录
f, err := os.OpenFile(path, os.O_WRONLY, os.ModeDir)
if err != nil {
fmt.Println("OpenFile err: ", err)
return
}
defer f.Close()
// 读取目录项
info, err:= f.Readdir(-1) // -1: 读取目录中所有目录项
if err != nil {
fmt.Println("Readdir err: ", err)
return
}
// 变量返回的切片
for _, fileInfo := range info {
if fileInfo.IsDir() { // 是目录
fmt.Println(fileInfo.Name(), " 是一个目录")
} else {
fmt.Println(fileInfo.Name(), " 是一个文件")
}
}
}
MMU
虚拟内存映射单元
缓冲区
文件读写分为,系统缓存和用户缓冲,用户缓存就是写代码时候创建的缓存,而用户缓存则是系统内部的缓存调度,不是每次读写都是操作磁头扇区等硬件,而是系统尽可能的预读入缓输出,减少硬件交互,代码的读取和写入都是读取和写入系统缓冲区,真正什么时候写入硬盘,有系统内部IO优化算法操作。