上节回顾
file一些操作os包下
FileInfo : 获取文件信息
Reader : 读
Write:写
文件复制
mkdir
create
remove
Seeker接口
设置光标的位置,读写文件
type Seeker interface { // 1、offset 偏移量 3 // 2、whence 如何设置,当前光标的位置。 Seek(offset int64, whence int) (int64, error) } // 如何让光标在第三个位置? // 1、找到当前光标在哪里 // a) 文件的头部, 0 // b) 文件的尾部 end // c) 在任意地方,相对位置。 const ( SeekStart = 0 // 表示相对于文件的开头 SeekCurrent = 1 // 表示相对于当前光标所在的位置 SeekEnd = 2 // 相对于文件的末尾 )
关于seek的使用
package main import ( "fmt" "io" "os" ) func main() { // 读取文件 file, _ := os.OpenFile("D:\\Environment\\GoWorks\\src\\xuego\\lesson11\\a.txt", os.O_RDWR, os.ModePerm) // defer close defer file.Close() // 测试seek // 相对开始位置。io.SeekStart // 相对于文件末尾, io.SeekEnd file.Seek(2, io.SeekStart) buf := []byte{0} file.Read(buf) fmt.Println(string(buf)) // 相对于当前位置 file.Seek(3, io.SeekCurrent) file.Read(buf) fmt.Println(string(buf)) // 在结尾追加内容 file.Seek(0, io.SeekEnd) file.WriteString("hahahaha") }
断点续传
思考几个问题:
1、如果你要传的文件很大,70G,是否有方法可以缩短耗时?
-
将文件拆分
-
同时多线程进行下载
2、如果在文件传递过程中,程序被迫中断(断电、断网、内存满了..),下次重启之后,文件是否还需要重头再传?
-
希望能够继续上传或者下载
3、传递文件的时候,支持暂停和恢复上传?假设这个两个操作分布在重启前后?
-
支持!
file、read、write、seek
思路:
1、需要记住上一次传递了多少数据、temp.txt => 记录
2、如果被暂停或者中断了,我们就可以读取这个temp.txt的记录,恢复上传
3、删除temp.txt
所有人必须要要全部理解的一段代码
package main import ( "fmt" "io" "os" "strconv" ) // 断点续传 func main() { // 传输源文件地址 srcFile := "C:\\Users\\遇见狂神说\\Desktop\\client\\gp.png" // 传输的目标位置 destFile := "D:\\Environment\\GoWorks\\src\\xuego\\lesson11\\server\\gp-upload.png" // 临时记录文件 tempFile := "D:\\Environment\\GoWorks\\src\\xuego\\lesson11\\temp.txt" // 创建对应的file对象,连接起来 file1, _ := os.Open(srcFile) file2, _ := os.OpenFile(destFile, os.O_CREATE|os.O_RDWR, os.ModePerm) file3, _ := os.OpenFile(tempFile, os.O_CREATE|os.O_RDWR, os.ModePerm) defer file1.Close() defer file2.Close() fmt.Println("file1/2/3 文件连接建立完毕") // 1、读取temp.txt file3.Seek(0, io.SeekStart) buf := make([]byte, 1024, 1024) n, _ := file3.Read(buf) // 2、转换成string - 数字。 countStr := string(buf[:n]) count, _ := strconv.ParseInt(countStr, 10, 64) fmt.Println("temp.txt中记录的值为:", count) // 5120 // 3、设置读写的偏移量 file1.Seek(count, io.SeekStart) file2.Seek(count, io.SeekStart) fmt.Println("file1/2 光标已经移动到了目标位置") // 4、开始读写(复制、上传) bufData := make([]byte, 1024, 1024) // 5、需要记录读取了多少个字节 total := int(count) for { // 读取数据 readNum, err := file1.Read(bufData) if err == io.EOF { // file1 读取完毕了 fmt.Println("文件传输完毕了") file3.Close() os.Remove(tempFile) break } // 向目标文件中写入数据 writeNum, err := file2.Write(bufData[:readNum]) // 将写入数据放到 total中, 在这里total 就是传输的进度 total = total + writeNum // temp.txt 存放临时记录数据 file3.Seek(0, io.SeekStart) // 将光标重置到开头 file3.WriteString(strconv.Itoa(total)) } }
遍历文件夹
下去一定要自己实现
package main import ( "fmt" "log" "os" ) // cd /d 文件夹路径 // tree /F , 查看当前文件夹下的所有文件 // 遍历文件夹 // 1、读取当前文件夹下的所有文件 // 2、如果是文件夹,进入文件夹,继续读取里面的所有文件 // 3、设置一些结构化代码 func main() { dir := "D:\\Environment\\GoWorks\\src\\xuego" tree(dir, 0) } // 日常调试测试常用fmt输出 、 工作中or项目中更多是log日志输出 func tree(dir string, level int) { // 编写层级 tabString := "|--" for i := 0; i < level; i++ { tabString = "| " + tabString } // 获取目录 ReadDir, 返回目录信息[]DirEntry,多个文件信息 fileInfos, err := os.ReadDir(dir) if err != nil { log.Println(err) } // 遍历出来所有文件之后,获取里面的单个文件 for _, file := range fileInfos { // 文件夹中文件的全路径展示 filename := dir + "\\" + file.Name() fmt.Println(tabString + file.Name()) // 如果是文件夹,再次遍历 if file.IsDir() { tree(filename, level+1) } } }
bufio
Go语言自带的IO操作包。bufio,使用这个包可以大幅提升文件的读写效率。
buf: 缓冲区.
io操作效率本身是还可以的,频繁访问本地磁盘文件(效率低)
所以说 bufio ,提供了一个缓冲区,读和写都先在缓冲区中,最后再一次性读取或者写入到文件里,降低访问本地磁盘的次数。
bufio写入
package main import ( "bufio" "fmt" "log" "os" ) // bufio 的应用 func main() { file, err := os.Open("D:\\Environment\\GoWorks\\src\\xuego\\lesson11\\demo01.go") if err != nil { log.Println(err) } defer file.Close() // 读取文件 // 创建一个bufio包下的 reader对象。 //bufioReader := bufio.NewReader(file) //buf := make([]byte, 1024) //n, err := bufioReader.Read(buf) //fmt.Println("读取到了多少个字节:", n) // 读取键盘的输入 // 键盘的输入,实际上是流 os.Stdin inputReader := bufio.NewReader(os.Stdin) // delim 到哪里结束读取 readString, _ := inputReader.ReadString('\n') fmt.Println("读取键盘输入的信息:", readString) }
bufio写出
package main import ( "bufio" "fmt" "os" ) // 写入 func main() { file, _ := os.OpenFile("D:\\Environment\\GoWorks\\src\\xuego\\lesson11\\a.txt", os.O_RDWR|os.O_CREATE, os.ModePerm) defer file.Close() // bufio fileWrite := bufio.NewWriter(file) writeNum, _ := fileWrite.WriteString("kuangshen") fmt.Println("writeNum:", writeNum) // 发现并没有写出到文件,是留在了缓冲区,所以我们需要调用 flush 刷新缓冲区 // 手动刷新进文件 fileWrite.Flush() }