go语言实现大文件分割与合并

前言

最近遇到这么个情况,有朋友特意录制了一段视频给我,想发给我。但是视频一不小心录制的太大了,有6G这么大。发送过来遇到了很大的麻烦。使用网盘的话速度太慢了,不能忍。后来发现了文叔叔这个工具。

后续

这个工具具有不限速,不用安装等特点,很方便,只有有浏览器就可以使用,所以使用手机也可以发送接收文件。但是有个问题是免费版单个文件最大只能4G。

后来尝试了很多工具,例如使用剪映把视频剪成几段,但是因为视频太大了,打开都崩溃。后来试着使用压缩工具压缩,可是压缩完还是很大,大于4G。(发稿时又变成5G了)

无奈之下,只能自己写程序来把大文件分割成小文件,然后再用文叔叔传给我,最后我用程序合并就ok了。所以使用什么写呢?python最简单,但是需要对方安装python解释器,想想就头痛。用java写?之前写过,但是还是要对方安装jdk。所以似乎GO是唯一的选项了。

真的忽然觉得,关键时候,用go真香,来根华子。

附上代码和使用方式

伸手党下载地址

http://www.azhangbaobao.cn:8888/

使用方式

1.拆分: (-f 加要拆分的文件名)

  ./split_and_merge.exe -f  ./azhang.mp4

合并:(可以额外指定文件名 -o 加输出的文件名,默认是azhang.mp4)

  ./split_and_merge.exe -a merge

上代码

GO代码:

package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"math"
	"os"
	"path/filepath"
)

const chunkSize = 4000000000

//const chunkSize = 50000000
var (
	action  string
	infile  string
	outfile string
)

func split(infile string) {
	if infile == "" {
		panic("请输入正确的文件名")
	}

	fileInfo, err := os.Stat(infile)
	if err != nil {
		if os.IsNotExist(err) {
			panic("文件不存在")
		}
		panic(err)
	}

	num := math.Ceil(float64(fileInfo.Size()) / chunkSize)

	fi, err := os.OpenFile(infile, os.O_RDONLY, os.ModePerm)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("要拆分成%.0f份\n", num)
	b := make([]byte, chunkSize)
	var i int64 = 1
	for ; i <= int64(num); i++ {
		fi.Seek((i-1)*chunkSize, 0)
		if len(b) > int(fileInfo.Size()-(i-1)*chunkSize) {
			b = make([]byte, fileInfo.Size()-(i-1)*chunkSize)
		}
		fi.Read(b)
		ofile := fmt.Sprintf("./%d.part", i)
		fmt.Printf("生成%s\n", ofile)
		f, err := os.OpenFile(ofile, os.O_CREATE|os.O_WRONLY, os.ModePerm)
		if err != nil {
			panic(err)
		}
		f.Write(b)
		f.Close()
	}
	fi.Close()
	fmt.Println("拆分完成")

}
func merge(outfile string) {
	fii, err := os.OpenFile(outfile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, os.ModePerm)
	if err != nil {
		panic(err)
		return
	}
	part_list, err := filepath.Glob("./*.part")
	if err != nil {
		panic(err)
		return
	}
	fmt.Printf("要把%v份合并成一个文件%s\n", part_list, outfile)
	i := 0
	for _, v := range part_list {
		f, err := os.OpenFile(v, os.O_RDONLY, os.ModePerm)
		if err != nil {
			fmt.Println(err)
			return
		}
		b, err := ioutil.ReadAll(f)
		if err != nil {
			fmt.Println(err)
			return
		}
		fii.Write(b)
		f.Close()
		i++
		fmt.Printf("合并%d个\n", i)
	}
	fii.Close()
	fmt.Println("合并成功")
}
func main() {
	flag.StringVar(&action, "a", "split", "请输入用途:split/merge 默认是split")
	flag.StringVar(&infile, "f", "", "请输入文件名")
	flag.StringVar(&outfile, "o", "azhang.mp4", "请输入要合并的文件名")
	flag.Parse()
	if action == "split" {
		split(infile)
	} else if action == "merge" {
		merge(outfile)
	} else {
		panic("-a只能输入split/merge")
	}
}

编译成exe文件

CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build  src/split_and_merge/split_and_merge.go

使用方式在上面哦