github.com/easysoft/zendata@v0.0.0-20240513203326-705bd5a7fd67/pkg/utils/file/file.go (about)

     1  package fileUtils
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"math/rand"
     8  	"os"
     9  	"os/exec"
    10  	"path/filepath"
    11  	"strings"
    12  	"time"
    13  
    14  	logUtils "github.com/easysoft/zendata/pkg/utils/log"
    15  
    16  	consts "github.com/easysoft/zendata/internal/pkg/const"
    17  	commonUtils "github.com/easysoft/zendata/pkg/utils/common"
    18  	i118Utils "github.com/easysoft/zendata/pkg/utils/i118"
    19  	stringUtils "github.com/easysoft/zendata/pkg/utils/string"
    20  	"github.com/easysoft/zendata/pkg/utils/vari"
    21  	"github.com/fatih/color"
    22  	"github.com/oklog/ulid/v2"
    23  	"github.com/snowlyg/helper/str"
    24  )
    25  
    26  func ReadFile(filePath string) string {
    27  	if !FileExist(filePath) {
    28  		return ""
    29  	}
    30  	buf := ReadFileBuf(filePath)
    31  	str := string(buf)
    32  	str = commonUtils.RemoveBlankLine(str)
    33  	return str
    34  }
    35  
    36  func ReadFileBuf(filePath string) []byte {
    37  	buf, err := os.ReadFile(filePath)
    38  	if err != nil {
    39  		return []byte(err.Error())
    40  	}
    41  
    42  	return buf
    43  }
    44  
    45  func WriteFile(filePath string, content string) {
    46  	dir := filepath.Dir(filePath)
    47  	MkDirIfNeeded(dir)
    48  
    49  	var d1 = []byte(content)
    50  	err := os.WriteFile(filePath, d1, 0666) //写入文件(字节数组)
    51  	check(err)
    52  }
    53  
    54  func RemoveExist(path string) {
    55  	os.Remove(path)
    56  }
    57  
    58  func check(e error) {
    59  	if e != nil {
    60  		panic(e)
    61  	}
    62  }
    63  
    64  func FileExist(path string) bool {
    65  	var exist = true
    66  	if _, err := os.Stat(path); os.IsNotExist(err) {
    67  		exist = false
    68  	}
    69  	return exist
    70  }
    71  
    72  func MkDirIfNeeded(dir string) error {
    73  	if !FileExist(dir) {
    74  		err := os.MkdirAll(dir, os.ModePerm)
    75  		return err
    76  	}
    77  
    78  	return nil
    79  }
    80  func RmFile(dir string) error {
    81  	if FileExist(dir) {
    82  		err := os.RemoveAll(dir)
    83  		return err
    84  	}
    85  
    86  	return nil
    87  }
    88  
    89  func IsDir(f string) bool {
    90  	fi, e := os.Stat(f)
    91  	if e != nil {
    92  		return false
    93  	}
    94  	return fi.IsDir()
    95  }
    96  
    97  func GetAbsolutePath(pth string) string {
    98  	if !IsAbsPath(pth) {
    99  		pth, _ = filepath.Abs(pth)
   100  	}
   101  
   102  	return pth
   103  }
   104  func GetAbsoluteDir(pth string) string {
   105  	pth = GetAbsolutePath(pth)
   106  	pth = filepath.Dir(pth)
   107  	pth = AddSepIfNeeded(pth)
   108  
   109  	return pth
   110  }
   111  
   112  func IsAbsPath(pth string) bool {
   113  	return filepath.IsAbs(pth) ||
   114  		strings.Index(pth, ":") == 1 // windows
   115  }
   116  
   117  func AddSepIfNeeded(pth string) string {
   118  	sepa := string(os.PathSeparator)
   119  
   120  	if strings.LastIndex(pth, sepa) < len(pth)-1 {
   121  		pth += sepa
   122  	}
   123  	return pth
   124  }
   125  
   126  func GetWorkDir(root string) (ret string, err error) {
   127  	if root != "" {
   128  		if !IsAbsPath(root) {
   129  			root, err = filepath.Abs(root)
   130  			if err != nil {
   131  				logUtils.PrintToWithColor(i118Utils.I118Prt.Sprintf("root_invalid", root), color.FgRed)
   132  				os.Exit(1)
   133  			}
   134  		}
   135  		ret = AddSepIfNeeded(root)
   136  
   137  		return
   138  	}
   139  
   140  	dir := ""
   141  
   142  	isRelease := commonUtils.IsRelease()
   143  	isRunAsBackendProcess := commonUtils.IsRunAsBackendProcess()
   144  
   145  	if !isRelease { // debug
   146  		dir, _ = os.Getwd()
   147  
   148  	} else {
   149  		p, _ := exec.LookPath(os.Args[0])
   150  		logUtils.PrintTo(fmt.Sprintf("p=%v", p))
   151  
   152  		if isRunAsBackendProcess {
   153  			name := "gui"
   154  			if commonUtils.GetOs() == "mac" {
   155  				name = "zd.app"
   156  			}
   157  
   158  			if strings.Index(p, name) > -1 {
   159  				guiDir := p[:strings.LastIndex(p, name)]
   160  				dir = guiDir[:strings.LastIndex(guiDir, string(os.PathSeparator))]
   161  			} else {
   162  				dir = filepath.Dir(p)
   163  			}
   164  
   165  		} else {
   166  			dir = filepath.Dir(p)
   167  			if FileExist(filepath.Join(dir, "tmp/cache/.data.db")) {
   168  				dir, _ = filepath.Abs(dir)
   169  			} else {
   170  				dir, _ = os.Getwd()
   171  			}
   172  
   173  		}
   174  	}
   175  
   176  	dir, _ = filepath.Abs(dir)
   177  	ret = AddSepIfNeeded(dir)
   178  
   179  	if !isRelease || vari.Verbose {
   180  		logUtils.PrintTo(fmt.Sprintf("isRelease = %t, isRunAsBackendProcess = %t, workDir = %s",
   181  			isRelease, isRunAsBackendProcess, ret))
   182  	}
   183  
   184  	return
   185  }
   186  
   187  func GetAbsDir(path string) string {
   188  	abs, _ := filepath.Abs(filepath.Dir(path))
   189  	abs = AddSepIfNeeded(abs)
   190  	return abs
   191  }
   192  
   193  func GetFileOrFolderDir(pth string) (ret string) {
   194  	if IsDir(pth) {
   195  		ret = pth
   196  	} else {
   197  		ret = filepath.Dir(pth)
   198  	}
   199  
   200  	ret, _ = filepath.Abs(ret)
   201  	ret = AddSepIfNeeded(ret)
   202  
   203  	return
   204  }
   205  
   206  func GetResProp(from, currFileDir string) (resFile, resType, sheet string) { // from resource
   207  	if strings.LastIndex(from, ".yaml") > -1 { // yaml, ip.v1.yaml
   208  		resFile = ConvertResYamlPath(from, currFileDir)
   209  		resType = "yaml"
   210  	} else if strings.LastIndex(from, ".txt") > -1 {
   211  		resFile = ConvertResYamlPath(from, currFileDir)
   212  		resType = "text"
   213  	} else { // excel, like address.cn.v1.china
   214  		resFile, sheet = ConvertResExcelPath(from, currFileDir)
   215  		resType = "excel"
   216  	}
   217  
   218  	if resFile == "" {
   219  		resPath := vari.GlobalVars.ConfigFileDir + from
   220  		if !FileExist(resPath) { // in same folder with passed config file, like dir/name.yaml
   221  			resPath = vari.WorkDir + from
   222  			if !FileExist(resPath) { // in res file
   223  				resPath = ""
   224  			}
   225  		}
   226  		resFile = resPath
   227  	}
   228  
   229  	if !FileExist(resFile) {
   230  		resFile = ""
   231  	}
   232  
   233  	if resFile == "" {
   234  		color.New(color.FgCyan).Fprintf(color.Output, i118Utils.I118Prt.Sprintf("fail_to_find_res", from)+"\n")
   235  	}
   236  
   237  	return
   238  }
   239  
   240  func ConvertReferRangeToPath(file, currFile string) (path string) {
   241  	dir := GetAbsDir(currFile)
   242  	path = ConvertResYamlPath(file, dir)
   243  
   244  	if path == "" {
   245  		resPath := GetAbsDir(currFile) + file
   246  		if !FileExist(resPath) { // in same folder
   247  			resPath = vari.WorkDir + file
   248  			if !FileExist(resPath) { // in res file
   249  				resPath = ""
   250  			}
   251  		}
   252  		path = resPath
   253  	}
   254  
   255  	return
   256  }
   257  
   258  func ConvertResYamlPath(from, workDir string) (ret string) {
   259  	pth := namedFileExistInDir(from, workDir)
   260  	if pth != "" {
   261  		ret = pth
   262  		return
   263  	}
   264  
   265  	arr := strings.Split(from, ".")
   266  	for i := 0; i < len(arr); i++ {
   267  		dir := ""
   268  		if i > 0 {
   269  			dir = strings.Join(arr[:i], consts.PthSep)
   270  		}
   271  		file := strings.Join(arr[i:], ".")
   272  
   273  		relatPath := ""
   274  		if dir != "" {
   275  			relatPath = dir + consts.PthSep + file
   276  		} else {
   277  			relatPath = file
   278  		}
   279  
   280  		realPth0 := filepath.Join(workDir, relatPath)
   281  		realPth1 := vari.WorkDir + consts.ResDirYaml + consts.PthSep + relatPath
   282  		realPth2 := vari.WorkDir + consts.ResDirUsers + consts.PthSep + relatPath
   283  		if FileExist(realPth0) {
   284  			ret = realPth0
   285  			break
   286  		} else if FileExist(realPth1) {
   287  			ret = realPth1
   288  			break
   289  		} else if FileExist(realPth2) {
   290  			ret = realPth2
   291  			break
   292  		}
   293  	}
   294  
   295  	return
   296  }
   297  
   298  func ConvertResExcelPath(from, dir string) (ret, sheet string) {
   299  	pth := namedFileExistInDir(from, dir)
   300  	if pth != "" {
   301  		ret = pth
   302  		return
   303  	}
   304  
   305  	path1 := from // address.cn.v1
   306  	index := strings.LastIndex(from, ".")
   307  	path2 := from[:index] // address.cn.v1.china
   308  
   309  	paths := [2]string{path1, path2}
   310  	for index, filePath := range paths {
   311  
   312  		arr := strings.Split(filePath, ".")
   313  		for i := 0; i < len(arr); i++ {
   314  			dir := ""
   315  			if i > 0 {
   316  				dir = strings.Join(arr[:i], consts.PthSep)
   317  			}
   318  
   319  			tagFile := strings.Join(arr[i:], ".") + ".xlsx"
   320  
   321  			relatPath := ""
   322  			if dir != "" {
   323  				relatPath = dir + consts.PthSep + tagFile
   324  			} else {
   325  				relatPath = tagFile
   326  			}
   327  
   328  			realPth := vari.WorkDir + consts.ResDirData + consts.PthSep + relatPath
   329  			if FileExist(realPth) {
   330  				if index == 1 {
   331  					sheet = from[strings.LastIndex(from, ".")+1:]
   332  				}
   333  				ret = realPth
   334  				return
   335  			}
   336  		}
   337  	}
   338  
   339  	if ret == "" { // try excel dir
   340  		realPth := vari.WorkDir + consts.ResDirData + consts.PthSep +
   341  			strings.Replace(from, ".", consts.PthSep, -1)
   342  		if IsDir(realPth) {
   343  			ret = realPth
   344  			return
   345  		}
   346  	}
   347  
   348  	return
   349  }
   350  
   351  func GetFilesByExtInDir(folder, ext string, files *[]string) {
   352  	extArr := strings.Split(ext, ",")
   353  
   354  	folder, _ = filepath.Abs(folder)
   355  
   356  	if !IsDir(folder) {
   357  		if ext == "" || stringUtils.StrInArr(filepath.Ext(folder), extArr) {
   358  			*files = append(*files, folder)
   359  		}
   360  
   361  		return
   362  	}
   363  
   364  	dir, err := os.ReadDir(folder)
   365  	if err != nil {
   366  		return
   367  	}
   368  
   369  	for _, fi := range dir {
   370  		name := fi.Name()
   371  		if commonUtils.IgnoreFile(name) {
   372  			continue
   373  		}
   374  
   375  		filePath := AddSepIfNeeded(folder) + name
   376  		if fi.IsDir() {
   377  			GetFilesByExtInDir(filePath, ext, files)
   378  		} else if strings.Index(name, "~") != 0 && (ext == "" || stringUtils.StrInArr(filepath.Ext(filePath), extArr)) {
   379  			*files = append(*files, filePath)
   380  		}
   381  	}
   382  }
   383  
   384  func GetFileName(filePath string) string {
   385  	fileName := filepath.Base(filePath)
   386  	fileName = strings.TrimSuffix(fileName, filepath.Ext(filePath))
   387  
   388  	return fileName
   389  }
   390  
   391  func GetFilesInDir(folder, ext string, files *[]string) {
   392  	folder, _ = filepath.Abs(folder)
   393  
   394  	if !IsDir(folder) {
   395  		if filepath.Ext(folder) == ext {
   396  			*files = append(*files, folder)
   397  		}
   398  
   399  		return
   400  	}
   401  
   402  	dir, err := ioutil.ReadDir(folder)
   403  	if err != nil {
   404  		return
   405  	}
   406  
   407  	for _, fi := range dir {
   408  		name := fi.Name()
   409  		if commonUtils.IgnoreFile(name) {
   410  			continue
   411  		}
   412  
   413  		filePath := AddSepIfNeeded(folder) + name
   414  		if fi.IsDir() {
   415  			GetFilesInDir(filePath, ext, files)
   416  		} else if strings.Index(name, "~") != 0 && filepath.Ext(filePath) == ext {
   417  			*files = append(*files, filePath)
   418  		}
   419  	}
   420  }
   421  
   422  func ChangeFileExt(filePath, ext string) string {
   423  	ret := strings.TrimSuffix(filePath, filepath.Ext(filePath))
   424  	ret += ext
   425  
   426  	return ret
   427  }
   428  
   429  func AddPathSepRightIfNeeded(pth string) string {
   430  	if pth[len(pth)-1:] != consts.PthSep {
   431  		pth += consts.PthSep
   432  	}
   433  
   434  	return pth
   435  }
   436  func RemovePathSepLeftIfNeeded(pth string) string {
   437  	if strings.Index(pth, consts.PthSep) == 0 {
   438  		pth = pth[1:]
   439  	}
   440  
   441  	return pth
   442  }
   443  
   444  func namedFileExistInDir(file, dir string) (pth string) {
   445  	if IsAbsPath(file) { // abs path, return it
   446  		if FileExist(file) {
   447  			pth = file
   448  			return
   449  		} else {
   450  			return
   451  		}
   452  	} else {
   453  		file = filepath.Join(dir, file)
   454  		if FileExist(file) {
   455  			pth = file
   456  			return
   457  		}
   458  	}
   459  
   460  	return
   461  }
   462  
   463  func GetFilesFromParams(args []string) (files []string, count int) {
   464  	for _, arg := range args {
   465  		if strings.Index(arg, "-") != 0 {
   466  			files = append(files, arg)
   467  			count++
   468  		} else {
   469  			break
   470  		}
   471  	}
   472  
   473  	return
   474  }
   475  
   476  func HandleFiles(files []string) []string {
   477  	if len(files) != 2 {
   478  		return files
   479  	}
   480  
   481  	if files[0] == "" && files[1] != "" { // no defaultFile
   482  		files[0] = files[1]
   483  		files[1] = ""
   484  	} else if files[1] == "" && files[0] != "" { // no configFile
   485  		files[1] = files[0]
   486  		files[0] = ""
   487  	}
   488  
   489  	return files
   490  }
   491  
   492  func NewFileNameWithUlidPostfix(pth string) (ret string) {
   493  	return AddFilePostfix(pth, stringUtils.Ulid())
   494  }
   495  
   496  func AddFilePostfix(pth, postfix string) (ret string) {
   497  	ext := filepath.Ext(pth)
   498  
   499  	ret = pth[:strings.LastIndex(pth, ext)] + "-" + postfix + ext
   500  
   501  	return
   502  }
   503  
   504  func GetUploadFileName(name string) (ret string, err error) {
   505  	fns := strings.Split(strings.TrimPrefix(name, "./"), ".")
   506  	if len(fns) < 2 {
   507  		msg := fmt.Sprintf("文件名错误 %s", name)
   508  		err = errors.New(msg)
   509  		return
   510  	}
   511  
   512  	base := fns[0]
   513  	ext := fns[1]
   514  
   515  	entropy := rand.New(rand.NewSource(time.Now().UnixNano()))
   516  	ms := ulid.Timestamp(time.Now())
   517  	rand, _ := ulid.New(ms, entropy)
   518  
   519  	ret = str.Join(base, "-", strings.ToLower(rand.String()), ".", ext)
   520  
   521  	return
   522  }