1. 主要借助io包里的Seeker接口
type Seeker interface {
Seek(offset int64, whence int) (int64, error)
//设置指针光标的位置:
第一个参数:偏移量,
第二个参数:如何设置:
const (
SeekStart = 0 // 相对于光标开头
SeekCurrent = 1 // 相对于光标当前
SeekEnd = 2 // 相对于光标结尾
)
}
fileName := "E:/GoPath/src/a/aa.txt"
//打开文件,注意是否有此文件
//file, err := os.Open(fileName)
file, err := os.OpenFile(fileName, os.O_RDWR, os.ModePerm)
if err != nil {
log.Fatal(err)
}
defer file.Close()
bs := []byte{0}
file.Read(bs)
fmt.Println(string(bs))
file.Seek(4, io.SeekStart)
file.Read(bs)
fmt.Println(string(bs))
file.Seek(4, io.SeekCurrent)
file.Read(bs)
fmt.Println(string(bs))
file.Seek(0, io.SeekEnd)
file.WriteString("ABC")
2. 断点续传应用场景(文件的传递:文件的复制)
- 文件比较大,如何缩短耗时?
- 如果文件传递过程中,程序被迫中断,再次重启是否需要重头开始?
- 传递过程中,是否支持暂停和恢复?
3. 原理:通过一个临时文件记录已传递文件的大小,字节的位置; 思路:边复制,边记录复制的总量
func main() {
srcFile := "E:/GoPath/src/a/1.png"
//获取文件名
destFile := srcFile[strings.LastIndex(srcFile, "/")+1: ]
fmt.Println(destFile)
temFile := destFile + "temp.txt"
fmt.Println(temFile)
file1,err := os.Open(srcFile)
HandleErr(err)
file2,err := os.OpenFile(destFile, os.O_CREATE|os.O_WRONLY, os.ModePerm)
HandleErr(err)
file3,err := os.OpenFile(temFile, os.O_CREATE|os.O_RDWR, os.ModePerm)
HandleErr(err)
defer file1.Close()
defer file2.Close()
//1: 先读取临时文件的数据,再seek
file3.Seek(0, io.SeekStart)//从0开始读
bs := make([]byte, 100,100)//一个文件的长度
n1,err := file3.Read(bs)
//HandleErr(err)
countStr := string(bs[:n1])
count,err := strconv.ParseInt(countStr, 10, 64)
//HandleErr(err)
fmt.Println(count)
//2:设置偏移量;设置读,写的位置
file1.Seek(count, io.SeekStart)
file2.Seek(count, io.SeekStart)
data := make([]byte, 1024, 1024)//用来复制文件
n2 := -1 //读取的数据量
n3 := -1 //写出的数据量
total := int(count) //读取的总量
//3: 复制文件
for{
n2,err = file1.Read(data)
if err == io.EOF || n2 == 0 {
fmt.Println("复制完毕", total)
file3.Close()
os.Remove(temFile)
break
}
n3,err = file2.Write(data[:n2])
total += n3
//将复制的总量,存储到临时文件中
file3.Seek(0, io.SeekStart)
file3.WriteString(strconv.Itoa(total))
fmt.Print("total:%d\n", total)
//假装断电
if total > 8000{
//panic("假装断电看看")
}
}
}
func HandleErr(err error){
if err != nil {
log.Fatal(err)
}
}