Go IO学习笔记

IO

I input 输入 、写
O output 输出 、 读

os常用包

操作文件和文件夹相关的

func main() {
	fixx, err := os.Stat("./pojo/User.go")
	if err != nil {
		return
	}
	fmt.Println(fixx.Name()) //取文件的名字
	fmt.Println(fixx.Mode()) //文件的权限
	// linux中2种权限定义方式,一种字母,一种8进制,-代表文件,d代表目录, r代表可读04,w代表可写02,x代表可执行01 也可以用0777代替
	fmt.Println(fixx.ModTime()) //最后的修改时间
	fmt.Println(fixx.IsDir())   //是不是文件夹
	fmt.Println(fixx.Size())    //文件的大小(字节)
	//反射获取文件更详细的信息
	fmt.Println(fixx.Sys()) //&{16 {2247817508 30994319} {4286871947 30994434} {1396014605 30994321} 0 0}

}

创建文件夹和多级文件夹

func main() {
	//创建单级目录,已有的话会报错。
	err := os.Mkdir("./pojo2", os.ModePerm) //后面是权限,也可以用0777代替
	if err != nil {
		fmt.Println(err)
	}
	//创建多级目录,已有的话不会报错,没有的话会创建
	err = os.MkdirAll("./pojo2/a/b/c", os.ModePerm) //后面是权限,也可以用0777代替
	if err != nil {
		fmt.Println(err)
	}

}

删除

func main() {
	//删除单目录,里面没文件的,其他情况会报错
	err := os.Remove("./pojo2/a/b/c")
	if err != nil {
		fmt.Println(err)
	}
	//删除多目录,里面有文件的,谨慎使用
	err1 := os.RemoveAll("./pojo2")
	if err1 != nil {
		fmt.Println(err1)
	}

}

创建文件

func main() {
	//参数是一个,地址加文件,重名文件会覆盖.
	file, err0 := os.Create("./pojo/a.txt")
	if err0 != nil {
		fmt.Println(err0)
	}
	fmt.Println(file)
	fmt.Println(file.Name())
	//参数是2个,每次返回的后缀不一样,不知道干嘛的.
	file1, err := os.CreateTemp("./pojo", "a.txt")
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(file1)
	fmt.Println(file1.Name())
}

读写文件

1.先获取文件的指针,判断文件是否权限
2.然后os.open()建立文件流,用openfile()还可以设置打开的权限
3.创建byte类型切片
4.用os.read(切片)读出来,返回2个参数,一个长度,一个err

不知道为什么狂神打出来的aaa带了一堆缓冲区的,我的没带。

func main() {
	//建立文件流,如果没有os.O_APPEND参数,写的时候是覆盖,有的话是追加
	openinfo, err := os.OpenFile("pojo/a.txt", os.O_WRONLY|os.O_WRONLY|os.O_APPEND, os.ModePerm)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer openinfo.Close()
	//创建byte切片
	bs := make([]byte, 1024, 1024)
	bs = []byte{65, 66, 67, 68, 69, 70}
	//写数据到文件
	i, err1 := openinfo.Write(bs)
	if err1 != nil {
		fmt.Println(err1)
		return
	}
	i1, _ := openinfo.WriteString("hello,顺大大")
	fmt.Println(i)
	fmt.Println(i1)

}

手动复制文件

copy函数
func copy(ywj, mbwenj string, size int) {

	ywjfile, err := os.Open(ywj)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer ywjfile.Close()
	mbfile, err1 := os.OpenFile(mbwenj, os.O_WRONLY|os.O_CREATE, 777)
	if err1 != nil {
		fmt.Println(err1)
		return
	}
	defer mbfile.Close()
	//缓冲区
	buf := make([]byte, size)
	for {
		//读
		n, err := ywjfile.Read(buf)
		if err == io.EOF || n == 0 {
			fmt.Println("文件复制完毕了")
			break
		}
		//写
		_, err2 := mbfile.Write(buf[:n])
		if err2 != nil {
			fmt.Println("写出失败", err2)
		}
	}
}
系统自带的io.copy(目标文件,源文件)函数
func copy2(mubiao, yuan string) {
	//源文件流
	ywjfile, err := os.Open(yuan)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer ywjfile.Close()
	//目标文件流
	mbfile, err1 := os.OpenFile(mubiao, os.O_WRONLY|os.O_CREATE, 777)
	if err1 != nil {
		fmt.Println(err1)
		return
	}
	defer mbfile.Close()

	written, _ := io.Copy(mbfile, ywjfile)
	fmt.Println("文件大小", written)

}
系统自带的读写函数

不建议用到大文件,内存可能扛不住

func copy3(mubiao, yuan string) {
	//读源文件 存到缓冲区,返回缓冲区切片
	bytes, _ := os.ReadFile(yuan)
	//写到目标文件,3个参数,目标地址,缓冲区,权限
	os.WriteFile(mubiao, bytes, 777)
}

断点续传

Seek函数

用来设置文件读写时的光标位置,3个入参。
进行写的时候,即使文件是可读可写的,也必须用os.OpenFile加一个写的权限,不然写不进去.
读可以读,写必须Openfile加权限

func main() {
	filea := "./pojo/a.txt"
	//fileInfoa, _ := os.Open(filea)
	//文件本身就是可读写的,也必须用可读写打开,不然没法进行读写.
	fileInfoa, _ := os.OpenFile(filea, os.O_RDWR, 777)

	defer fileInfoa.Close()
	//业务
	//用来设置读写文件流时光标的位置
	fileInfoa.Seek(3, io.SeekStart) //0代表开始,1代表当前,2代表结尾

	//设置缓冲区
	buf := []byte{0}
	//读
	fileInfoa.Read(buf)
	fmt.Println(string(buf))
	//当光标在末尾时,可以写
	fileInfoa.Seek(0, io.SeekEnd)
	n, err := fileInfoa.WriteString("hahah")
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(n)
}
实操断点续传

1.创建源文件,目标文件,临时文件的流
2.读临时文件中记录的行数
3.开始读,写,并且记录传输进度
4.通过painc()模拟断电,继续传输

这里遇到个大坑 排查半天,那就是open.file的第三个参数,777和os.ModePerm不一样,要写成0777才可以.

func main() {
	//逻辑 源文件读完,写到目标文件,写的时候记录光标的位置数到临时文件,中间断电,恢复后,继续断电前的光标位置传输

	//1.设置源文件,目标文件,临时文件的路径
	yuanwenjian := "E:\\Environment\\GoWorks\\src\\pojo\\xxx.png"
	mubiaowenjian := "E:\\Environment\\GoWorks\\src\\xxxcopy.png"
	linshiwenjian := "E:\\Environment\\GoWorks\\src\\pojo\\a.txt"
	//建立流
	file1, _ := os.Open(yuanwenjian)
	file2, _ := os.OpenFile(mubiaowenjian, os.O_RDWR|os.O_CREATE, os.ModePerm) //写777就续传不上了
	file3, _ := os.OpenFile(linshiwenjian, os.O_RDWR|os.O_CREATE, 0777)

	defer file1.Close()
	defer file2.Close()

	//2.取临时文件中的数据
	file3.Seek(0, 0)                //将光标放到最开始
	buf := make([]byte, 1024, 1024) //设置临时文件的缓冲区
	n, err := file3.Read(buf)       //读临时文件到buf,返回长度lin
	fmt.Println(buf, err)
	countstr := string(buf[:n]) //取buf从0到lin,并转为string类型
	fmt.Println("countstr:", countstr)
	//将countstr转为数字
	count, _ := strconv.ParseInt(countstr, 10, 64)
	//3.设置光标位置seek
	file1.Seek(count, 0) //从count开始读
	file2.Seek(count, 0) //从count开始写

	bufData := make([]byte, 1024, 1024)
	total := int(count)
	//4.传输并记录进度到临时文件
	for {
		//读
		readNum, err := file1.Read(bufData)
		if err == io.EOF {
			fmt.Println("读取完毕", err)
			file3.Close()
			os.Remove(linshiwenjian) //读取完毕销毁临时文件
			break
		}
		//写
		writeNum, _ := file2.Write(bufData[:readNum])
		total = total + writeNum //最新行数total+写进去的行数

		//将传输进度记录,先重置临时文件光标,在记录
		file3.Seek(0, 0)
		file3.WriteString(strconv.Itoa(total))

		//模拟断电
		/*if total > 1000 {
			panic("断电了")
		}*/
	}
}

bufio

封装了io与缓冲区的包

func main() {
	//创建流
	file, _ := os.OpenFile("./pojo/b.txt", os.O_RDWR, os.ModePerm)
	//bufio读,返回reader对象
	reader := bufio.NewReader(file)
	buf := make([]byte, 1024)
	//用reader对象读
	n, _ := reader.Read(buf)
	fmt.Println(string(buf[:n]))
	//读取键盘输入
	newReader := bufio.NewReader(os.Stdin)
	str, _ := newReader.ReadString('\n')
	fmt.Println("键盘输入为", str)

	//bufio写
	writer := bufio.NewWriter(file)
	writeString, _ := writer.WriteString("hahahh")
	fmt.Println(writeString) //6
	//发现并没有写进去文件原因是缓冲区大小是1024,没有满
	//手动将缓冲区数据,写入文件
	writer.Flush()

}

手写递归文件夹

func main() {
	address := "E:\\Environment\\GoWorks\\src"

	list(address, 0)
}

// 传入地址,和层级,初始为0级
func list(address string, tabint int) {

	//表示层级关系的符合,每次增加层级tab就增加
	tab := "|--"
	for i := 0; i < tabint; i++ {
		tab = "|	" + tab
	}

	//os.Reader()方法,读文件夹,返回指针和err
	dir, _ := os.ReadDir(address)
	
	//forr返回2个,一个貌似是计数,,一个是文件对象
	for _, file := range dir {
		//拼接文件对象的名字
		filename := address + "\\" + file.Name()
		fmt.Printf("%s%s\n", tab, filename)
		//如果是文件夹,继续递归这个方法,并且层级加1,拼接的名字对象也会变长.
		if file.IsDir() {
			list(filename, tabint+1)
		}
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tigeraowu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值