1 Star 1 Fork 0

bon-ami / eztools

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
cfg.go 7.42 KB
一键复制 编辑 原始数据 按行查看 历史
Allen Tse 提交于 2022-11-09 08:41 . zip funcs and more file funcs
package eztools
import (
"encoding/csv"
"encoding/xml"
"io"
"os"
"path/filepath"
"github.com/shibukawa/configdir"
"golang.org/x/text/encoding"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
)
func xmlPrepare(data interface{}, indent string) ([]byte, error) {
bytes, err := xml.MarshalIndent(data, "", indent)
if err != nil {
return nil, err
}
var PREFIX = []byte("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
return append(PREFIX, bytes...), nil
}
// XMLWrite writes file from input structure
// by a full path (with .xml extension)
// this reformats the file with indent provided
func XMLWrite(file string, data interface{}, indent string) error {
slc, err := xmlPrepare(data, indent)
if err != nil {
return err
}
return FileWrite(file, slc)
}
// XMLWriter writes with writer from input structure
// wrt is not Close()'d
func XMLWriter(wrt io.WriteCloser, data interface{}, indent string) error {
if wrt == nil {
return ErrOutOfBound
}
slc, err := xmlPrepare(data, indent)
if err != nil {
return err
}
_, err = wrt.Write(slc)
return err
}
// XMLWriteNoCreate writes existing file from input structure
// by a full path (with .xml extension)
// this reformats the file with indent provided
func XMLWriteNoCreate(file string, data interface{}, indent string) error {
slc, err := xmlPrepare(data, indent)
if err != nil {
return err
}
return FileWriteNoCreate(file, slc)
}
// XMLWriteDefault writes file from input structure
// by a module name for both system config directory and file name
// home dir and current dir are also candidates in case of failure
// this reformats the file with indent provided
func XMLWriteDefault(module string, data interface{},
indent string) (pathFound string, err error) {
dirs := []string{GetCfgDir("", module)}
home, err := os.UserHomeDir()
if err == nil {
dirs = append(dirs, home)
}
dirs = append(dirs, ".")
var failPaths string
for _, dir1 := range dirs {
pathFound = filepath.Join(dir1, module+".xml")
err = XMLWrite(pathFound, data, indent)
Log("trying", pathFound, err)
if err == nil {
return
}
failPaths += "; " + pathFound
}
return failPaths, err
}
// XMLRead reads file into input structure
// Return values from os.Stat(), os.ReadFile() and xml.Unmarshal()
func XMLRead(file string, data interface{}) error {
if _, err := os.Stat(file); err != nil {
return err
}
bytes, err := os.ReadFile(file)
if err != nil {
return err
}
return xml.Unmarshal(bytes, data)
}
// XMLReader reads with reader into input structure
// rdr is not Close()'d
func XMLReader(rdr io.ReadCloser, data interface{}) error {
bytes, err := io.ReadAll(rdr)
if err != nil {
return err
}
return xml.Unmarshal(bytes, data)
}
// GetCfgDir returns config directory by system
// Parameters: vendor can be empty
func GetCfgDir(vendor, module string) string {
dirs := configdir.New(vendor, module)
folders := dirs.QueryFolders(configdir.Global)
//folders[0].WriteFile("cfg.xml", nil)
return folders[0].Path
}
// XMLReadDefault reads config file into input structure from
// 1. givenpath,
// 2. or given file name (plus .xml) under one of these dirs,
// current dir, home dir, or system's config dir.
// the file name is taken as module name for system's config dir.
//
// Return values: full file name with path
//
// ErrNoValidResults=no file parsable
// other errors from XMLRead()
func XMLReadDefault(path, file string, cfg interface{}) (
pathFound string, err error) {
if len(path) > 0 {
err = XMLRead(path, cfg)
if err == nil {
return path, err
}
}
if len(file) < 1 {
return "", ErrNoValidResults
}
home, _ := os.UserHomeDir()
cfgPaths := [...]string{".", home, GetCfgDir("", file)}
for _, path1 := range cfgPaths {
pathFound = filepath.Join(path1, file+".xml")
err = XMLRead(pathFound, cfg)
if err == nil {
if Debugging && Verbose > 1 {
Log(pathFound, "found and read")
}
return
} else {
// TODO: return err for failure to access or parse
if Debugging && Verbose > 1 {
Log(pathFound, err)
}
}
}
return "", ErrNoValidResults
}
// CfgEZtools defines the structure of a predefined config xml
type CfgEZtools struct {
// Root of the XML
Root xml.Name `xml:"eztools"`
// Cmt = comments
Cmt string `xml:",comment"`
// Text is not used
Text string `xml:",chardata"`
Db CfgEZtoolsDb `xml:"db"`
Map []CfgEZtoolsMap `xml:"map"`
}
const (
EncodingGbk = "gbk"
)
var encodings = [...]struct {
str string
enc encoding.Encoding
}{
{EncodingGbk, simplifiedchinese.GBK},
}
// ListEnc list all valid encoding strings for
//
// CSVReadWtEnc()
// UTF-8 is default and not listed.
func ListEnc() (ret []string) {
for _, e := range encodings {
ret = append(ret, e.str)
}
return ret
}
type file2Writer func(f *os.File, encodingStr string) *transform.Writer
func csvWriteWtWriter(file string, data [][]string, f2w file2Writer,
encodingStr string, createIfNeeded bool) (err error) {
_, err = os.Stat(file)
var g int
g = os.O_WRONLY | os.O_TRUNC
if !createIfNeeded {
if err != nil {
return
}
} else {
g |= os.O_CREATE
}
f, err := os.OpenFile(file, g, FileCreatePermission)
if err != nil {
return
}
defer f.Close()
var wrt *csv.Writer
if f2w != nil {
wrt = csv.NewWriter(f2w(f, encodingStr))
} else {
wrt = csv.NewWriter(f)
}
return wrt.WriteAll(data)
}
// CSVWriteNoCreate writes data to existing file by a full path (with .csv extension)
func CSVWriteNoCreate(file string, data [][]string) error {
return csvWriteWtWriter(file, data, nil, "", false)
}
// CSVWrite writes UTF-8 file with slice of slice of string
func CSVWrite(file string, data [][]string) (err error) {
return csvWriteWtWriter(file, data, nil, "", true)
}
func csvWriterTransform(f *os.File, encodingStr string) *transform.Writer {
var encING encoding.Encoding
for _, v := range encodings {
if v.str == encodingStr {
encING = v.enc
break
}
}
return transform.NewWriter(f,
encoding.ReplaceUnsupported(encING.NewEncoder()))
}
// CSVWriteWtEnc writes file with slice of slice of string, with specified encoding
func CSVWriteWtEnc(file, encodingStr string, data [][]string) (err error) {
return csvWriteWtWriter(file, data,
csvWriterTransform, encodingStr, true)
}
// CSVWriteWtEncNoCreate writes existing file with slice of slice of string, with specified encoding
func CSVWriteWtEncNoCreate(file, encodingStr string, data [][]string) (err error) {
return csvWriteWtWriter(file, data,
csvWriterTransform, encodingStr, false)
}
type file2Reader func(*os.File) *transform.Reader
func csvReadWtReader(file string, f2r file2Reader) (ret [][]string, err error) {
if _, err = os.Stat(file); err != nil {
return
}
f, err := os.Open(file)
if err != nil {
return
}
defer f.Close()
var rdr *csv.Reader
if f2r != nil {
rdr = csv.NewReader(f2r(f))
} else {
rdr = csv.NewReader(f)
}
//rd := csv.NewReader(rdr)
return rdr.ReadAll()
}
// CSVRead reads UTF-8 file into slice of slice of string
func CSVRead(file string) (ret [][]string, err error) {
return csvReadWtReader(file, nil)
}
// CSVReadWtEnc reads file into slice of slice of string, with specified encoding
func CSVReadWtEnc(file, encodingStr string) (ret [][]string, err error) {
return csvReadWtReader(file,
func(f *os.File) *transform.Reader {
var encING encoding.Encoding
for _, v := range encodings {
if v.str == encodingStr {
encING = v.enc
break
}
}
return transform.NewReader(f,
/*encoding.ReplaceUnsupported*/ (encING.NewDecoder()))
})
}
Go
1
https://gitee.com/bon-ami/eztools.git
git@gitee.com:bon-ami/eztools.git
bon-ami
eztools
eztools
v4.11.0

搜索帮助