檔案複製(Go語言實現)

恩嗯發表於2020-10-05
在這裡插package main

import (
	"fmt"
	"io"
	"os"
	"strconv"
	"time"
)

type MyCopy struct{}

func NewMyCopy() *MyCopy {
	return new(MyCopy)
}

//儲存上次檔案讀取到的位置
var last string = "./last"

/**
* 功能:檔案複製(支援斷點續傳)
* Seek(offset int64, whence int) (ret int64, err error) 表示設定當前游標的位置
* offset int,設定多個位元組
* whence int,從哪開始 0->距離檔案開頭 1->當前位置 2->距離檔案末尾
*
 */
func (c *MyCopy) CopyFile(dstFile, srcFile string) (int, error) {
	src, err := os.Open(srcFile)

	if err != nil {
		fmt.Println("open srcFile failed: %v", err)
		return -1, err
	}

	des, err := os.OpenFile(dstFile, os.O_CREATE|os.O_WRONLY, 0775)
	if err != nil {
		fmt.Println("open desFile failed: %v", err)
		return -1, err
	}

	defer src.Close()
	defer des.Close()

	lastPos := c.GetLastPosition()
	position := 0

	if lastPos > 0 {
		src.Seek(int64(lastPos), io.SeekStart) //0
		des.Seek(int64(lastPos), io.SeekStart) //0
		position = lastPos
	}

	fmt.Printf("當前讀取位置為:%d\n", position)
	var buf [128]byte

	for {

		count, err := src.Read(buf[:])
		if err == io.EOF {
			os.Remove(last) //檔案拷貝結束,刪除記錄內容
			break
		}

		if err != nil {
			fmt.Printf("read file context failed:%v\n", err)
			break
		}

		position += count
		fmt.Printf("copy cap:%d\r", position)
		time.Sleep(100 * time.Millisecond) //模擬網路延遲
		des.Write(buf[:count])
		c.WritePosition([]byte(fmt.Sprintf("%d", position)))
		/*
			if position == 10 {
				fmt.Println("模擬中斷傳輸")
				break
			}*/
	}
	fmt.Println("end============================================================")
	return position, nil
}

/*
 獲取上次斷點位置
*/
func (c *MyCopy) GetLastPosition() int {
	file, err := os.Open(last)

	if err != nil {
		return -1
	}

	defer file.Close()

	var buff [128]byte

	n, err := file.Read(buff[:])
	if err != nil {
		fmt.Println("Read lastfile failed: ", err)
		return -1
	}

	v, err := strconv.Atoi(string(buff[0:n]))
	if err != nil || v < 0 {
		fmt.Println("Atoi error")
		return -1
	}

	return v
}

/**
* 寫入當前讀取到位置
 */
func (c *MyCopy) WritePosition(v []byte) {
	//Write(b []byte) (n int, err error)
	file, err := os.OpenFile(last, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
	if err != nil {
		fmt.Printf("write last position to failed:%v\n", err)
		return
	}
	file.Write(v)
	defer file.Close()
}

func main() {j
	c := NewMyCopy()
	c.CopyFile("a.txt", "employer.go")
}
入程式碼片

相關文章