Golang-记使用go语言操作文件

546 阅读2分钟

自2019下半年开始,学徒在有意无意的,时断时续的学习golang,需要找些机会去实践go编程,找不机会就硬找。

学徒使用UWP版的bilibili客户端下载了一些bilibili平台的教学视频(众所周知,bilibili是一个专业的学习平台),然而视频下载完后,发现下载的视频文件并非存储在一个文件目录中,非常不方便将整个系列视频添加到播放列表或者分享交流。所以学徒打算将下载的文件整理出来,整理的过程正是使用Golang实现。

实现需求

  • 未整理前,具体看图
  • 整理后

实现步骤

从上图看可以列一下编程步骤。

  • 读取ini文件拿到系列视频名称
  • 以系列视频名称新创建文件目录
  • 读取json文件获取视频文件名称
  • 拷贝视频文件并重命名至新创建的文件目录中

编码实现

需要安装的库

# 安装mahonia,编码转换,解决中文乱码问题
$ go get github.com/axgle/mahonia

# 安装go-ini,帮助解析ini文件,获取键值
$ go get gopkg.in/ini.v1
#
$ go get github.com/go-ini/ini

编码分了三个文件

  • vars.go,存储文件整理的一些参数
package main

var bilibiliDownloadPath = "E:\\resource\\downloads\\bilibili"
var destPath = "E:\\videos"
  • bva.go,bilibili视频文件整理用到的方法
package main

import (
	"encoding/json"
	"fmt"
	"github.com/axgle/mahonia" //编码转换
	"gopkg.in/ini.v1"
	"io"
	"io/ioutil"
	"os"
)

var enc = mahonia.NewDecoder("gbk")

// 根据文件名,段名,键名获取ini的值
func getIniValue(filename, expectSection, expectKey string) string {
	// enc := mahonia.NewDecoder("gbk")
	iniFile, err := ini.Load(filename)
	if err != nil {
		return ""
	}

	val := iniFile.Section(expectSection).Key(expectKey).String()
	return enc.ConvertString(val)
}

type VideoInfo struct {
	PartName string
}

// 根据文件名,段名,键名获取ini的值
func getJsonValue(filename string) string {
	// enc := mahonia.NewDecoder("gbk")
	jsonFile, err := os.Open(filename)

	if err != nil {
		return ""
	}

	jsonBytes, err := ioutil.ReadAll(jsonFile)

	var videoInfo VideoInfo

	json.Unmarshal(jsonBytes, &videoInfo)

	return videoInfo.PartName
}

// 文件Copy
func CopyFile(srcName, destName string) error {
	src, err := os.Open(srcName)
	if err != nil {
		return fmt.Errorf("File Open Failed.")
	}
	defer src.Close()

	dest, err := os.Create(destName)
	if err != nil {
		return fmt.Errorf("File Create Failed.")
	}
	defer dest.Close()

	_, err = io.Copy(dest, src)
	if err != nil {
		return fmt.Errorf("File Copy Failed.")
	}

	return nil
}
  • main.go,程序入口
package main

import (
	"fmt"
	"io/ioutil"
	"os"
)

func main() {
	// 获取所有系列视频目录
	fis, err := ioutil.ReadDir(bilibiliDownloadPath)
	if err != nil {
		fmt.Println("ReadDir Failed! Path:" + bilibiliDownloadPath)
		return
	}

	// 处理每个系列目录
	for _, fi := range fis {
		if fi.IsDir() {
			HandlerSingleSeries(fi)
		}
	}
}

func HandlerSingleSeries(fi os.FileInfo) {
	fiPath := bilibiliDownloadPath + "\\" + fi.Name() // 系列目录

	// 读取ini文件拿到系列视频名称
	iniFilePath := fiPath + "\\desktop.ini"
	seriesName := getIniValue(iniFilePath, ".ShellClassInfo", "InfoTip")

	if seriesName != "" {
		// 以系列视频名称新创建文件目录
		seriesPath := destPath + "\\" + seriesName
		err := os.Mkdir(seriesPath, os.ModePerm)
		if err != nil {
			fmt.Print("Mkdir Failed! Path:" + seriesPath)
		}

		vfis, err := ioutil.ReadDir(fiPath)
		if err != nil {
			fmt.Println("ReadDir Failed! Path:" + fiPath)
			return
		}

		for _, vfi := range vfis {
			if vfi.IsDir() {
				// 读取json文件获取视频文件名称
				jsonFileName := fiPath + "\\" + vfi.Name() + "\\" + fi.Name() + ".info"
				pName := getJsonValue(jsonFileName) // 分P名称,视频文件名
				if pName != "" {
					// 拷贝视频文件并重命名至新创建的文件目录中
					fiSrcPath := fiPath + "\\" + vfi.Name() + "\\" + fi.Name() + "_" + vfi.Name() + "_0.flv"
					fiDestPath := seriesPath + "\\" + pName + ".flv"
					CopyFile(fiSrcPath, fiDestPath)
				}
			}
		}
	}
}

程序上传至:github

结束语

Golang的编程体验很不错,入门算是非常简单的。变量的声明比较新颖,可以通过下载github上的库直接引用。Golang有着天然支持高并发编程的有点,又作为区块链的主要编程语言,还是很有学习意义的。

引用

  1. Golang高并发的理解