diff --git a/.gitignore b/.gitignore index c63dd5e..823baf1 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,6 @@ hugo.linux # Temporary lock file while building /.hugo_build.lock +.idea +.vscode diff --git a/file.go b/file.go new file mode 100644 index 0000000..b1785e4 --- /dev/null +++ b/file.go @@ -0,0 +1,279 @@ +// Package serialize ... +// +// Description : 文件读写相关工具 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2021-04-26 6:00 下午 +package serialize + +import ( + "errors" + "io" + "net/http" + "os" + "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 { + fileInfoArr := strings.Split(filePath, ".") + if len(fileInfoArr) < 2 { + return errors.New("未知的文件类型") + } + var ( + parseFunc func(filePath string, receiver interface{}) error + ) + + fileExt := strings.ToLower(fileInfoArr[len(fileInfoArr)-1]) + switch fileExt { + case "json": + parseFunc = f.ReadJSONContent + case "yml": + fallthrough + case "yaml": + parseFunc = f.ReadYmlContent + case "ini": + parseFunc = f.ReadIniContent + 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) + return nil == err || os.IsExist(err), (nil == err || os.IsExist(err)) && !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 +} diff --git a/go.mod b/go.mod index 0e5cc42..f86a19e 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,10 @@ module git.zhangdeman.cn/zhangdeman/serialize go 1.20 + +require ( + git.zhangdeman.cn/zhangdeman/util v0.0.0-20230810093304-ccb4045065c4 + github.com/BurntSushi/toml v1.3.2 + github.com/go-ini/ini v1.67.0 + gopkg.in/yaml.v3 v3.0.1 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..20d53fa --- /dev/null +++ b/go.sum @@ -0,0 +1,13 @@ +git.zhangdeman.cn/zhangdeman/util v0.0.0-20230810093304-ccb4045065c4 h1:MgZ2f1BkUtfP8D6uDX9S8o+V4wYUw76HlAw3xCH9epA= +git.zhangdeman.cn/zhangdeman/util v0.0.0-20230810093304-ccb4045065c4/go.mod h1:tPl6isAsRQLZrX8G3/8fCdhN4OcZypdmdHR/PDkd2PY= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= +github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/json.go b/json.go new file mode 100644 index 0000000..284cbf6 --- /dev/null +++ b/json.go @@ -0,0 +1,137 @@ +// Package serialize ... +// +// Description : json 工具函数 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2021-09-14 8:38 下午 +package serialize + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "os" + "reflect" +) + +var ( + // JSON ... + JSON *ownJSON +) + +func init() { + JSON = &ownJSON{} +} + +// ownJSON ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 15:01 2022/5/14 +type ownJSON struct { +} + +// UnmarshalWithNumber 解析json +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 8:39 下午 2021/9/14 +func (oj *ownJSON) UnmarshalWithNumber(byteData []byte, receiver interface{}) error { + decoder := json.NewDecoder(bytes.NewReader(byteData)) + decoder.UseNumber() + return decoder.Decode(receiver) +} + +// UnmarshalWithNumberForIOReader ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 8:43 下午 2021/9/14 +func (oj *ownJSON) UnmarshalWithNumberForIOReader(ioReader io.ReadCloser, receiver interface{}) error { + decoder := json.NewDecoder(ioReader) + decoder.UseNumber() + return decoder.Decode(receiver) +} + +// UnmarshalWithNumberForString 字符串转结构体 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 21:50 2023/7/22 +func (oj *ownJSON) UnmarshalWithNumberForString(input string, receiver interface{}) error { + return oj.UnmarshalWithNumber([]byte(input), receiver) +} + +// MarshalForByte 序列化并返回字节数组 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 21:56 2023/7/22 +func (oj *ownJSON) MarshalForByte(input interface{}) []byte { + byteData, _ := json.Marshal(input) + return byteData +} + +// MarshalForString 序列化并返回字符串 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 21:56 2023/7/22 +func (oj *ownJSON) MarshalForString(input interface{}) string { + byteData := oj.MarshalForByte(input) + return string(byteData) +} + +// ConsoleOutput ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 5:45 下午 2021/11/5 +func (oj *ownJSON) ConsoleOutput(data interface{}) { + var out bytes.Buffer + switch reflect.TypeOf(data).Kind() { + case reflect.Slice: + fallthrough + case reflect.Array: + fallthrough + case reflect.Map: + fallthrough + case reflect.Ptr: + byteData, _ := json.Marshal(data) + _ = json.Indent(&out, []byte(string(byteData)+"\n"), "", "\t") + _, _ = out.WriteTo(os.Stdout) + return + case reflect.Int: + fallthrough + case reflect.Int8: + fallthrough + case reflect.Int16: + fallthrough + case reflect.Int32: + fallthrough + case reflect.Int64: + fallthrough + case reflect.Uint: + fallthrough + case reflect.Uint8: + fallthrough + case reflect.Uint16: + fallthrough + case reflect.Uint32: + fallthrough + case reflect.Uint64: + fallthrough + case reflect.Float32: + fallthrough + case reflect.Float64: + fallthrough + case reflect.String: + _ = json.Indent(&out, []byte(fmt.Sprintf("%v\n", data)), "", "\t") + _, _ = out.WriteTo(os.Stdout) + return + default: + fmt.Println("") + } +}