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 }