赞
踩

主要实现了根据文本文件里面的内容,自动更名所选文件夹里面的文件名称
1.创建txt文本文件,输入内容程序界面中"目录文件"选择目前创建的文本文件
例:

2.选择需要批量更改名字的文件夹

3.选择路径后,程序点击"开始更名",便会自动更名

4.结果


命令:
1.go get fyne.io/fyne/v2
2.go get fyne.io/fyne/cmd/fyne
1.将静态资源编译为 go 文件 (在自己的项目目录打开终端执行):fyne bundle fav.png >> bundled.go
2. 打开 bundled.go 文件会看到一个变量 resourceFavPng
3.设置窗口图标,任务栏图标
//主要代码
a := app.New()
a.SetIcon(resourceFavPng) //本地运行的注释,否则报错,打包的时候在把此行代码打开
package main import ( "YHSoft/Demo/GUIDemo/FyneDemo/02_RenameFileName/models" //更换成自己的项目路径 "errors" "fmt" "fyne.io/fyne/v2" "fyne.io/fyne/v2/app" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/layout" "fyne.io/fyne/v2/storage" "fyne.io/fyne/v2/widget" "github.com/flopp/go-findfont" "io/ioutil" "log" "os" "path/filepath" "strconv" "strings" "time" "unicode" ) func main() { //新建一个app a := app.New() //设置窗口栏,任务栏图标 a.SetIcon(resourceIconPng) //新建一个窗口 w := a.NewWindow("自动化更名程序V1.0") //主界面框架布局 MainShow(w) //尺寸 w.Resize(fyne.Size{Width: 500, Height: 100}) //w居中显示 w.CenterOnScreen() //循环运行 w.ShowAndRun() err := os.Unsetenv("FYNE_FONT") if err != nil { return } } var tileInfo string var done = make(chan bool) var stop = make(chan int, 1) var num int64 // MainShow 主界面函数 func MainShow(w fyne.Window) { //var ctrl *beep.Ctrl title := widget.NewLabel("自动化更名程序") hello := widget.NewLabel("目录文件:") entry1 := widget.NewEntry() //文本输入框 //entry1.SetText("E:\\rename_temp2\\123.txt") dia1 := widget.NewButton("打开", func() { //回调函数:打开选择文件对话框 fd := dialog.NewFileOpen(func(reader fyne.URIReadCloser, err error) { if err != nil { dialog.ShowError(err, w) return } if reader == nil { log.Println("Cancelled") return } entry1.SetText(reader.URI().Path()) //把读取到的路径显示到输入框中 }, w) fd.SetFilter(storage.NewExtensionFileFilter([]string{".txt"})) //打开的文件格式类型 fd.Show() //控制是否弹出选择文件目录对话框 }) text := widget.NewMultiLineEntry() //多行输入组件 //text.Disable() //禁用输入框,不能更改数据 labelLast := widget.NewLabel("发飙的蜗牛 ALL Right Reserved") //labelLast := widget.NewLabel(" ") label4 := widget.NewLabel("文件路径:") entry2 := widget.NewEntry() //entry2.SetText("E:\\rename_temp2\\宝岗路停车场项目幕墙施工图PDF") dia2 := widget.NewButton("打开", func() { dialog.ShowFolderOpen(func(list fyne.ListableURI, err error) { if err != nil { dialog.ShowError(err, w) return } if list == nil { log.Println("Cancelled") return } //设置输入框内容 entry2.SetText(list.Path()) }, w) }) //开始更名按钮 bt3 := widget.NewButton("开始 更名", func() { go func() { if (entry1.Text != "") && (entry2.Text != "") { text.SetText("") text.Refresh() if num != 0 { stop <- 1 return } else { err := generateTxt(entry1.Text, entry2.Text, text) if err != nil { dialog.ShowError(err, w) } text.Refresh() } } else { dialog.ShowError(errors.New("读取TXT文件错误"), w) } }() }) //停止更名按钮 bt4 := widget.NewButton("停止 更名", func() { go func() { done <- false }() }) head := container.NewCenter(title) v1 := container.NewBorder(layout.NewSpacer(), layout.NewSpacer(), hello, dia1, entry1) v4 := container.NewBorder(layout.NewSpacer(), layout.NewSpacer(), label4, dia2, entry2) v5 := container.NewHBox(bt3, bt4) v5Center := container.NewCenter(v5) ctnt := container.NewVBox(head, v1, v4, v5Center, text, labelLast) //控制显示位置顺序 w.SetContent(ctnt) } //设置字体 func init() { fontPaths := findfont.List() for _, fontPath := range fontPaths { //fmt.Println(fontPath) //楷体:simkai.ttf //黑体:simhei.ttf //微软雅黑:msyh.ttc if strings.Contains(fontPath, "simkai.ttf") { err := os.Setenv("FYNE_FONT", fontPath) if err != nil { return } break } } } //读取数据校验数据 func generateTxt(inPath, outPath string, text *widget.Entry) error { //标题 tileInfo += "开始处理,正在读取文件...\n" text.SetText(tileInfo) nameList,err := models.GetStrList(inPath) if err != nil{ tileInfo += "读取文件出错...\n" text.SetText(tileInfo) } //获取文件路径的文件 files, _ := ioutil.ReadDir(outPath) var fileNameList []string for _, file := range files { // 带扩展名的文件名 fullFilename := file.Name() //添加文件数据到切片中 fileNameList = append(fileNameList, fullFilename) } if len(nameList) == 0 || len(fileNameList) == 0{ tileInfo += "已停止处理...\n" text.SetText(tileInfo) //设置多行显示控件中的内容 return errors.New("找不到路径或路径下不存在此文件") } if len(nameList) != len(fileNameList) { tileInfo += "已停止处理...\n" text.SetText(tileInfo) //设置多行显示控件中的内容 return errors.New("目录行数与文件行数不相等,请检查!") } renameFile(nameList, fileNameList, outPath, text) return nil } //操作更名文件 func renameFile(nameList []string, fileNameList []string, outPath string, text *widget.Entry) { var newName string //遍历更改 for index, fullFilename := range fileNameList { select { case <-done: //读管道中内容,没有内容前,阻塞 //扩展名 fileExt := filepath.Ext(fullFilename) //fmt.Println("nameList[index]=",nameList[index]) defaultName := nameList[index] //文本文件初始名称 var defaultNameCode []string var defaultNameNewCode string rune := []rune(defaultName) for i := len(rune); i > 0; i-- { if !unicode.Is(unicode.Han, rune[i-1]) { defaultNameCode = append(defaultNameCode, string(rune[i-1])) } else { break } } //重新编排名称编号 for i := len(defaultNameCode); i > 0; i-- { defaultNameNewCode += defaultNameCode[i-1] } //fmt.Println("defaultName=", defaultName) //重组新名称 newName = strconv.Itoa(index+1) + " " + strings.ReplaceAll(defaultName, defaultNameNewCode, "") + " " + defaultNameNewCode // 不带扩展名的文件名 //filenameOnly := strings.TrimSuffix(fullFilename, fileExt) //将每个文件名后面加上1,扩展名不变 err := os.Rename(outPath+`\`+fullFilename, outPath+`\`+newName+fileExt) if err != nil { fmt.Println("err=", err) } tileInfo += "处理数据文件:" + fullFilename + "\n" time.Sleep(time.Second * 1) text.SetText(tileInfo) //设置多行显示控件中的 内容 tileInfo += "停止更名...\n" text.SetText(tileInfo) //设置多行显示控件中的内容 num = num + 1 <-stop //读管道中内容,没有内容前,阻塞 default: //扩展名 fileExt := filepath.Ext(fullFilename) //fmt.Println("nameList[index]=",nameList[index]) defaultName := nameList[index] //文本文件初始名称 var defaultNameCode []string var defaultNameNewCode string rune := []rune(defaultName) for i := len(rune); i > 0; i-- { if !unicode.Is(unicode.Han, rune[i-1]) { defaultNameCode = append(defaultNameCode, string(rune[i-1])) } else { break } } //重新编排名称编号 for i := len(defaultNameCode); i > 0; i-- { defaultNameNewCode += defaultNameCode[i-1] } //fmt.Println("defaultName=", defaultName) //重组新名称 newName = strconv.Itoa(index+1) + " " + strings.ReplaceAll(defaultName, defaultNameNewCode, "") + " " + defaultNameNewCode // 不带扩展名的文件名 //filenameOnly := strings.TrimSuffix(fullFilename, fileExt) //将每个文件名后面加上1,扩展名不变 err := os.Rename(outPath+`\`+fullFilename, outPath+`\`+newName+fileExt) if err != nil { fmt.Println("err=", err) } tileInfo += "处理数据文件:" + fullFilename + "\n" //time.Sleep(time.Second * 1) text.SetText(tileInfo) //设置多行显示控件中的 内容 } } tileInfo += "处理完毕!" text.SetText(tileInfo) //设置多行显示控件中的内容 num = 0 }
package models import ( "bufio" "fmt" "github.com/axgle/mahonia" "io" "os" "strings" ) //读取txt文件,自动判断编码格式 func GetStrList(path string)([]string,error){ f, err := os.Open(path) //打开目录路径txt文件 if err != nil { return nil, err } defer f.Close() //最后关闭文件 r := bufio.NewReader(f) buf := make([]byte, 1024) var res string _, err = r.Read(buf) if err != nil && err != io.EOF { return nil,err } res = GetStrCoding(buf) if res == "UTF8" { return GetTextContentUTF8(path),nil } else { return GetTextContentGbk(path),nil } } //读取gbk编码格式的文件 func GetTextContentGbk(txtPath string) []string { f, err := os.Open(txtPath) //打开目录路径txt文件 if err != nil { fmt.Println("err=", err) } defer f.Close() decoder := mahonia.NewDecoder("gbk") r := bufio.NewReader(decoder.NewReader(f)) chunks := []byte{} buf := make([]byte, 1024) for { n, err := r.Read(buf) if err != nil && err != io.EOF { panic(err) } if 0 == n { break } chunks = append(chunks, buf[:n]...) } nameStr := strings.ReplaceAll(string(chunks), "\r\n", ",") return strings.Split(nameStr, ",") } //读取utf8编码格式的文件 func GetTextContentUTF8(txtPath string) []string { f, err := os.Open(txtPath) //打开目录路径txt文件 if err != nil { fmt.Println("err=", err) } defer f.Close() r := bufio.NewReader(f) chunks := []byte{} buf := make([]byte, 1024) for { n, err := r.Read(buf) if err != nil && err != io.EOF { panic(err) } if 0 == n { break } chunks = append(chunks, buf[:n]...) } nameStr := strings.ReplaceAll(string(chunks), "\r\n", ",") return strings.Split(nameStr, ",") } const ( GBK string = "GBK" UTF8 string = "UTF8" UNKNOWN string = "UNKNOWN" ) //判断文本文件格式 func GetStrCoding(data []byte) string { if isUtf8(data) == true { return UTF8 } else if isGBK(data) == true { return GBK } else { return UNKNOWN } } func isGBK(data []byte) bool { length := len(data) var i = 0 for i < length { if data[i] <= 0x7f { //编码0~127,只有一个字节的编码,兼容ASCII码 i++ continue } else { //大于127的使用双字节编码,落在gbk编码范围内的字符 if data[i] >= 0x81 && data[i] <= 0xfe && data[i+1] >= 0x40 && data[i+1] <= 0xfe && data[i+1] != 0xf7 { i += 2 continue } else { return false } } } return true } func preNUm(data byte) int { var mask byte = 0x80 var num int = 0 //8bit中首个0bit前有多少个1bits for i := 0; i < 8; i++ { if (data & mask) == mask { num++ mask = mask >> 1 } else { break } } return num } func isUtf8(data []byte) bool { i := 0 for i < len(data) { if (data[i] & 0x80) == 0x00 { // 0XXX_XXXX i++ continue } else if num := preNUm(data[i]); num > 2 { // 110X_XXXX 10XX_XXXX // 1110_XXXX 10XX_XXXX 10XX_XXXX // 1111_0XXX 10XX_XXXX 10XX_XXXX 10XX_XXXX // 1111_10XX 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX // 1111_110X 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX // preNUm() 返回首个字节的8个bits中首个0bit前面1bit的个数,该数量也是该字符所使用的字节数 i++ for j := 0; j < num-1; j++ { //判断后面的 num - 1 个字节是不是都是10开头 if (data[i] & 0xc0) != 0x80 { return false } i++ } } else { //其他情况说明不是utf-8 return false } } return true }
代码可能不是最完美的,但是能实现想要的功能,也感谢各路大神的项目案列,也让自己有了相关代码的参考!
取之于民,用之于民!最后也欢迎各位的指教,共同交流进步!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。