// Package serialize ... // // Description : 文件读写相关工具 // // Author : go_developer@163.com<白茶清欢> // // Date : 2021-04-26 6:00 下午 package serialize import ( "errors" "git.zhangdeman.cn/zhangdeman/consts" "io" "net/http" "os" "path" "path/filepath" "strings" "github.com/BurntSushi/toml" "git.zhangdeman.cn/zhangdeman/util/define" "github.com/go-ini/ini" yml "gopkg.in/yaml.v3" ) var ( // File ... File *file ) func init() { File = &file{} } // file 文件相关操作 // // Author : go_developer@163.com<白茶清欢> // // Date : 14:08 2022/5/14 type file struct { } // GetProjectPath 获取项目路径(可执行文件所在目录) // // Author : go_developer@163.com<白茶清欢> // // Date : 10:32 下午 2021/4/26 func (f *file) GetProjectPath() (string, error) { rootPath, err := os.Getwd() if nil != err { return "", err } pathArr := strings.Split(rootPath, string(filepath.Separator)) if len(pathArr) > 0 { if pathArr[len(pathArr)-1] == "test" { rootPath = strings.Join(pathArr[0:len(pathArr)-1], "/") } } return rootPath, nil } // ReadYmlContent 读取yml配置问价,并解析到指定的结构体中 // // Author : go_developer@163.com<白茶清欢> // // Date : 10:35 下午 2021/4/26 func (f *file) ReadYmlContent(filePath string, result interface{}) error { if nil == result { return errors.New("接收读取结果的数据指针为NIL") } var ( fileContent []byte err error ) if fileContent, err = f.ReadFileContent(filePath); nil != err { return err } return yml.Unmarshal(fileContent, result) } // ReadJSONContent 读取JSON内容,并解析到指定的结构体中 // // Author : go_developer@163.com<白茶清欢> // // Date : 15:23 2022/6/9 func (f *file) ReadJSONContent(filePath string, result interface{}) error { if nil == result { return errors.New("接收读取结果的数据指针为NIL") } var ( fileContent []byte err error ) if fileContent, err = f.ReadFileContent(filePath); nil != err { return err } return JSON.UnmarshalWithNumber(fileContent, result) } // ReadIniContent 读取并解析ini文件 // // Author : go_developer@163.com<白茶清欢> // // Date : 13:21 2022/7/2 func (f *file) ReadIniContent(filePath string, result interface{}) error { if nil == result { return errors.New("接收读取结果的数据指针为NIL") } return ini.MapTo(result, filePath) } // ReadTomlContent 读取toml格式文件 // // Author : go_developer@163.com<白茶清欢> // // Date : 21:08 2023/7/31 func (f *file) ReadTomlContent(filePath string, result interface{}) error { if nil == result { return errors.New("接收读取结果的数据指针为NIL") } if _, err := toml.DecodeFile("example.toml", result); err != nil { return err } return nil } // ReadAnyFileContent 读取任意类型的文件并解析 // // Author : go_developer@163.com<白茶清欢> // // Date : 13:11 2022/7/2 func (f *file) ReadAnyFileContent(filePath string, receiver interface{}) error { var ( parseFunc func(filePath string, receiver interface{}) error ) filePathArr := strings.Split(filePath, "#@#") fileExt := "" filePath = filePathArr[0] if len(filePathArr) == 2 && len(filePathArr[1]) > 0 { fileExt = strings.ToLower(filePathArr[1]) } else { fileExt = strings.ToLower(path.Ext(filePath)) } switch fileExt { case consts.FileTypeJson: parseFunc = f.ReadJSONContent case consts.FileTypeYml: fallthrough case consts.FileTypeYaml: parseFunc = f.ReadYmlContent case consts.FileTypeIni: parseFunc = f.ReadIniContent case consts.FileTypeToml: parseFunc = f.ReadTomlContent default: return errors.New(fileExt + " 暂不支持当前格式的文件解析") } return parseFunc(filePath, receiver) } // ReadFileContent 读取文件内容 // // Author : go_developer@163.com<白茶清欢> // // Date : 10:37 下午 2021/4/26 func (f *file) ReadFileContent(filePath string) ([]byte, error) { if exist, isFile := f.IsFileExist(filePath); !exist || !isFile { //文件不存在或者是一个目录 return nil, errors.New(filePath + " 文件不存在或者是一个目录!") } //打开文件 var ( fileHandler *os.File err error ) if fileHandler, err = os.Open(filePath); nil != err { return nil, err } defer func() { if nil != fileHandler { // 关闭资源 _ = fileHandler.Close() } }() return io.ReadAll(fileHandler) } // IsFileExist 判断文件是否存在 // // Author : go_developer@163.com<白茶清欢> // // Date : 10:37 下午 2021/4/26 func (f *file) IsFileExist(filePath string) (bool, bool) { fileStat, err := os.Stat(filePath) isFileExist := nil == err || os.IsExist(err) return isFileExist, isFileExist && !fileStat.IsDir() } // GetFileMIMEType 获取本地文件的MIME类型 // // Author : go_developer@163.com<白茶清欢> // // Date : 17:15 2023/2/7 func (f *file) GetFileMIMEType(filePath string) (string, error) { var ( err error fileHandler *os.File ) if fileHandler, err = os.Open(filePath); nil != err { return "", err } // 只需要前 512 个字节就可以了 buffer := make([]byte, 512) if _, err = fileHandler.Read(buffer); nil != err { return "", err } contentType := http.DetectContentType(buffer) return contentType, nil } // ReadDirFileList 读取目录下的文件列表, 支持递归 // // Author : go_developer@163.com<白茶清欢> // // Date : 14:42 2023/7/31 func (f *file) ReadDirFileList(dirPath string, ignoreHiddenFile bool, isRecurve bool) ([]*define.FileInfo, error) { var ( err error fileList []os.DirEntry itemFileInfo os.FileInfo ) result := make([]*define.FileInfo, 0) if fileList, err = os.ReadDir(dirPath); nil != err { return result, err } for _, itemFile := range fileList { if ignoreHiddenFile && strings.HasPrefix(itemFile.Name(), ".") { // 或略隐藏文件、文件夹 continue } if itemFileInfo, err = itemFile.Info(); nil != err { return result, err } fileInfo := &define.FileInfo{ IsDir: itemFile.IsDir(), Name: itemFile.Name(), AbsolutePath: filepath.Join(dirPath, itemFile.Name()), Format: "", Size: itemFileInfo.Size(), ModifyTime: itemFileInfo.ModTime().Unix(), Mode: itemFileInfo.Mode(), FileList: make([]*define.FileInfo, 0), } if !fileInfo.IsDir { fileArr := strings.Split(fileInfo.Name, ".") if len(fileArr) >= 2 { fileInfo.Format = fileArr[len(fileArr)-1] } else { fileInfo.Format = "unknown" } } else { fileInfo.Format = "dir" } fileInfo.Format = strings.ToLower(fileInfo.Format) if fileInfo.IsDir && isRecurve { if fileInfo.FileList, err = f.ReadDirFileList(fileInfo.AbsolutePath, ignoreHiddenFile, isRecurve); nil != err { return result, err } } result = append(result, fileInfo) } return result, nil } // ReadFileListRecurve 递归读取文件内容 // // Author : go_developer@163.com<白茶清欢> // // Date : 15:26 2023/7/31 func (f *file) ReadFileListRecurve(rootDir string) ([]*define.FileInfo, error) { return nil, nil }