1 Star 1 Fork 0

D10.天地弦 / gobase

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
file.go 29.15 KB
一键复制 编辑 原始数据 按行查看 历史
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423
package gobase
import (
"bufio"
"crypto/md5"
"errors"
"fmt"
"io"
"math"
"os"
"os/exec"
"path"
"path/filepath"
"runtime"
"runtime/debug"
"strings"
"sync/atomic"
"time"
)
var (
PathSeparator = "\\"
RootPath = ""
cmd_exe_bin string = ""
)
type DiskStatus struct {
All uint64 `json:"all"`
Used uint64 `json:"used"`
Free uint64 `json:"free"`
}
var (
SIZE_KB uint64 = 1024
SIZE_MB = 1024 * SIZE_KB
SIZE_GB = 1024 * SIZE_MB
SIZE_TB = 1024 * SIZE_GB
)
/*
*
返回小数 0.1 = 10%
*/
func (this DiskStatus) FreePercent() float64 {
return float64(this.Free) / float64(this.All)
}
func (this DiskStatus) FreePercentStr(n int) string {
fmtstr := "%." + fmt.Sprintf("%d", n) + "f %%"
return fmt.Sprintf(fmtstr, this.FreePercent()*100)
}
//var (
// SIZE_KB uint64 = 1024
// SIZE_MB = 1024 * SIZE_KB
// SIZE_GB = 1024 * SIZE_MB
// SIZE_TB = 1024 * SIZE_GB
//)
/*
**
SizeStrToSize("1024MB") SizeStrToSize("1024B")
*/
func SizeStrToSize(str string) int64 {
num := 1
mult := 1024
if len(str) < 1 {
return StrToInt64Def(str, 0)
}
if len(str) > 1 {
chr := str[len(str)-1]
if chr == 'B' || chr == 'b' {
str = str[:len(str)-1]
}
if len(str) < 1 {
return StrToInt64Def(str, 0)
}
chr = str[len(str)-1]
switch chr {
case 'G', 'g':
num *= mult
fallthrough
case 'M', 'm':
num *= mult
fallthrough
case 'K', 'k':
num *= mult
str = str[0 : len(str)-1]
default:
return StrToInt64Def(str, 0)
}
}
v1 := StrToFloat64Def(str, 0)
return int64(v1 * float64(num))
}
func Size2GB(sizebytes uint64) float64 {
return float64(sizebytes) / float64(SIZE_GB)
}
func HumanFilesizeU(sizebytes uint64) string {
osize := sizebytes
rval := ""
t := float64(sizebytes) / float64(SIZE_TB)
if t > 1 {
rval = fmt.Sprintf("%.2f TB ", t)
return rval
}
t = float64(sizebytes) / float64(SIZE_GB)
if t > 1 {
rval = fmt.Sprintf("%.2f GB ", t)
return rval
}
t = float64(sizebytes) / float64(SIZE_MB)
if t > 1 {
rval = fmt.Sprintf("%.2f MB ", t)
return rval
}
t = float64(sizebytes) / float64(SIZE_KB)
if t > 1 {
rval = fmt.Sprintf("%.2f KB ", t)
return rval
}
return fmt.Sprintf("%d B", osize)
}
func HumanFilesize(sizebytes int64) string {
return HumanFilesizeU(uint64(sizebytes))
}
// ReadDir reads the directory named by dirname and returns
// a list of directory without sort.
func ReadDir(dirname string) ([]os.FileInfo, error) {
f, err := os.Open(dirname)
if err != nil {
return nil, err
}
list, err := f.Readdir(-1)
f.Close()
if err != nil {
return nil, err
}
return list, nil
}
/*
**
onerr 返回false 则返回退出当前目录的查找
*/
func searchAFile(path string, cmpfilepath *string, cmpfile *os.FileInfo, currlevel, maxlevel int, comparefunc func(cmp, cur os.FileInfo, mpath, cpath string) bool, onerr func(dirname string, err error) bool) error {
if currlevel >= maxlevel {
return nil
}
files, err := ReadDir(path)
if err != nil {
return err
}
for _, itm := range files {
if itm.IsDir() {
dirname := path + itm.Name() + PathSeparator
err := searchAFile(dirname, cmpfilepath, cmpfile, currlevel+1, maxlevel, comparefunc, onerr)
if err != nil && onerr != nil {
if !onerr(dirname, err) {
break
}
}
} else {
if comparefunc(*cmpfile, itm, *cmpfilepath, path) {
*cmpfile = itm
*cmpfilepath = path
}
}
}
return nil
}
func searchFiles(path string, afilepath *string, afile os.FileInfo, currlevel, maxlevel int, cbfunc func(m, c os.FileInfo, mpath, cpath string) bool) error {
if currlevel >= maxlevel {
return nil
}
files, err := ReadDir(path)
if err != nil {
return err
}
for _, itm := range files {
if itm.IsDir() {
if !cbfunc(afile, itm, *afilepath, path) {
break
}
err := searchFiles(path+itm.Name()+PathSeparator, afilepath, afile, currlevel+1, maxlevel, cbfunc)
if err != nil {
return err
}
} else {
if !cbfunc(afile, itm, *afilepath, path) {
break
}
}
}
return nil
}
/*
**
Range path下的文件和目录
maxlevel 表示目录层级
0: 表示搜索所有
1:表示获取当前目录(不会进入下一级目录)
fn: 如果返回 false 表示退出当前目录搜索, path为当前文件所在路径
onerr 返回false 则返回退出当前目录的range
*/
func RangeFiles(path string, maxlevel int, fn func(path string, file os.FileInfo) bool, onerr func(dirname string, err error) bool) error {
return rangeFiles(path, 0, maxlevel, fn, onerr)
}
/*
**
onerr 返回false 则返回退出当前目录的range
*/
func rangeFiles(path string, currlevel, maxlevel int, fn func(path string, file os.FileInfo) bool, onerr func(dirname string, err error) bool) error {
if currlevel >= maxlevel && maxlevel > 0 {
return nil
}
files, err := ReadDir(path)
if err != nil {
return err
}
for _, itm := range files {
if fn != nil {
if !fn(path, itm) {
break
}
}
if itm.IsDir() {
dirname := path + itm.Name() + PathSeparator
err := rangeFiles(dirname, currlevel+1, maxlevel, fn, onerr)
if err != nil && onerr != nil {
if !onerr(dirname, err) {
break
}
}
}
}
return nil
}
/*
1. 如果文件已经存在, 则对之前的文件进行更名
*/
func CheckRotateFile(filename string) error {
_, err := os.Lstat(filename)
if err == nil { // file exists
// Find the next available number
num := 1
fname := ""
// xx.2->xx.3, xx.1 -> xx.2
err_cnt := 0
var last_err error = nil
num = 100 - 1
for ; num >= 1; num-- {
fname = filename + fmt.Sprintf(".%d", num)
nfname := filename + fmt.Sprintf(".%d", num+1)
_, err = os.Lstat(fname)
if err == nil {
err = os.Rename(fname, nfname)
if err != nil {
err_cnt++
last_err = err
}
}
}
if last_err != nil {
fmt.Fprintf(os.Stderr, "[%s]CheckRotateFile, errcnt:%d, last err:%v\r\n", NowString(), err_cnt, err)
}
err = os.Rename(filename, fname)
if err != nil {
return fmt.Errorf("CheckRotateFile Rename: %s\n", err)
}
}
return nil
}
/*
1. 如果文件已经存在, 则对之前的文件进行更名, 更名失败 返回异常
2. 更名成功则创建新文件的os.file. 创建成功则返回, 失败,进行重试, 超过10次返回异常
创建的文件成功会被清空
*/
func CheckRotateFileAfterCreateFile(filename string) (fn *os.File, err error) {
j := 0
for {
err := CheckRotateFile(filename)
if err != nil {
return nil, err
}
fn, e1 := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
if e1 == nil {
return fn, nil
} else if j >= 10 {
return nil, e1
}
j++
}
return nil, nil // 应该不会到这一步
}
func CopyFile(src, dst string) (w int64, err error) {
srcFile, err := os.Open(src)
if err != nil {
return
}
defer srcFile.Close()
dstFile, err := os.OpenFile(dst, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil {
return
}
defer dstFile.Close()
return io.Copy(dstFile, srcFile)
}
func SearchFiles(path string, currlevel, maxlevel int, comparefunc func(m, c os.FileInfo, mpath, cpath string) bool) (string, error) {
var afile os.FileInfo
var passPath string
err := searchFiles(path, &passPath, afile, currlevel, maxlevel, comparefunc)
if afile == nil {
return "", err
} else {
return fmt.Sprintf("%s%s", passPath, afile.Name()), err
}
}
/**
* 查找符合条件的第一个文件
* comparefunc 返回true表示 cur比cmp文件更符合条件. cmp可能为空表示还没有查找到符合条件的文件, 判断时需要注意
*/
func SearchAFile(path string, currlevel, maxlevel int, comparefunc func(cmp, cur os.FileInfo, cmppath, curpath string) bool, onerr func(dirname string, err error) bool) (string, error) {
var afile os.FileInfo
var passPath string
if !strings.HasSuffix(path, PathSeparator) {
path += PathSeparator
}
err := searchAFile(path, &passPath, &afile, currlevel, maxlevel, comparefunc, onerr)
if afile == nil {
return "", err
} else {
return fmt.Sprintf("%s%s", passPath, afile.Name()), err
}
}
/**
* 查找符合条件的第一个文件
* comparefunc 返回true表示 cur比cmp文件更符合条件. cmp可能为空表示还没有查找到符合条件的文件, 判断时需要注意
*/
func SearchAFileEx(path string, currlevel, maxlevel int, comparefunc func(cmp, cur os.FileInfo, cmppath, curpath string) bool, onerr func(dirname string, err error) bool) (string, os.FileInfo) {
var afile os.FileInfo
var passPath string
if !strings.HasSuffix(path, PathSeparator) {
path += PathSeparator
}
searchAFile(path, &passPath, &afile, currlevel, maxlevel, comparefunc, onerr)
if afile == nil {
return "", nil
} else {
return passPath, afile
}
}
func ExtractFilePath(fileName string) string {
fileName = strings.Replace(fileName, "\\", "/", -1)
return path.Dir(fileName)
}
/*
*
路径最后带分隔符
*/
func Split2PathAndFileName(fileName string) (dir string, name string) {
if strings.ContainsRune(fileName, '\\') {
fileName = strings.ReplaceAll(fileName, "\\", "/")
dir, name = path.Split(fileName)
dir = strings.ReplaceAll(dir, "/", "\\")
return
} else {
return path.Split(fileName)
}
}
/*
**
带path分隔符
*/
func GetCurrentWorkingPath() (path string) {
path, _ = os.Getwd()
if len(path) > 0 {
path += PathSeparator
}
return
}
func GetCurrentDirectory() (path string, err error) {
dir, err := filepath.Abs(filepath.Dir(os.Args[0])) //返回绝对路径 filepath.Dir(os.Args[0])去除最后一个元素的路径
return dir, err
}
/**
* 最后不带路径符
*/
func GetExecuteFileDirectory() (path string) {
dir, _ := filepath.Abs(filepath.Dir(os.Args[0])) //返回绝对路径 filepath.Dir(os.Args[0])去除最后一个元素的路径
return dir
}
/*
*
返回执行文件名
*/
func GetExecuteFileName() (name string) {
return ExtractFileName(os.Args[0]) // 返回执行文件名
}
// get file modified time
func FileMTime(fp string) (time.Time, error) {
f, e := os.Stat(fp)
if e != nil {
return ZeroTime, e
}
return f.ModTime(), nil
}
// get file size as how many bytes
func FileSize(fp string) (int64, error) {
f, e := os.Stat(fp)
if e != nil {
return 0, e
}
return f.Size(), nil
}
func PathBase(path string) string {
if path == "" {
return "."
}
// Strip trailing slashes.
for len(path) > 0 && (path[len(path)-1] == '/' || path[len(path)-1] == '\\') {
path = path[0 : len(path)-1]
}
i := strings.LastIndexByte(path, '/')
j := strings.LastIndexByte(path, '\\')
if j > i {
i = j
}
if i >= 0 {
path = path[i+1:]
}
// If empty now, it had only slashes.
if path == "" {
return "/"
}
return path
}
func DeleteFileNameExt(fileName string) string {
fileExt := path.Ext(fileName)
rval := strings.TrimSuffix(fileName, fileExt)
return rval
}
/*
*
移除 文件或者文件夹
*/
func DeleteFileOrDir(strPath string) error {
return os.RemoveAll(strPath)
}
/*
*
"W:\\temp\\测试删除文件夹\\a.txt" -> a.txt
*/
func ExtractFileName(fileName string) string {
rval := PathBase(fileName)
return rval
}
func ExtractFileNameWithOutPathAndExt(fileName string) string {
rval := PathBase(fileName)
fileExt := path.Ext(rval)
rval = strings.TrimSuffix(rval, fileExt)
return rval
}
/*
**
如果返回的错误为nil,说明文件或文件夹存在
如果返回的错误类型使用os.IsNotExist()判断为true,说明文件或文件夹不存在
如果返回的错误为其它类型,则不确定是否在存在
*/
func PathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
func ForceCreatePath(strPath string) bool {
err := os.MkdirAll(strPath, 0777)
if err == nil {
return true
} else {
return os.IsExist(err)
}
}
func ForceAllPath(strPath string) error {
err := os.MkdirAll(strPath, 0777)
if err == nil {
return nil
} else if os.IsExist(err) {
return nil
} else {
return err
}
}
func ForceCreateFilePath(fileName string) error {
str := ExtractFilePath(fileName)
bv, _ := PathExists(str)
if !bv {
err := os.MkdirAll(str, 0777)
return err
} else {
return nil
}
}
func ExecCmdNoWait(cmdLine string) (*exec.Cmd, error) {
args := strings.Split(cmdLine, " ")
cmd := exec.Command(args[0], args[1:]...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Start()
return cmd, err
}
func ExecCmdNoWaitNoSettingIO(cmdLine string) (*exec.Cmd, error) {
args := strings.Split(cmdLine, " ")
cmd := exec.Command(args[0], args[1:]...)
err := cmd.Start()
return cmd, err
}
func ExecCmdLine(cmdLine string, arg_spliter string) error {
args := strings.Split(cmdLine, arg_spliter)
cmd := exec.Command(args[0], args[1:]...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
return err
}
/***
* exeshell("del *.log")
*/
func ExecShell(cmdLine string) error {
var cmd *exec.Cmd
if runtime.GOOS == "windows" {
cmd = exec.Command("cmd", "/C", cmdLine)
} else {
cmd = exec.Command(cmd_exe_bin, "-c", cmdLine)
}
return cmd.Run()
}
func GetExecShellCmd(cmdLine string) *exec.Cmd {
var cmd *exec.Cmd
if runtime.GOOS == "windows" {
cmd = exec.Command("cmd", "/C", cmdLine)
} else {
cmd = exec.Command(cmd_exe_bin, "-c", cmdLine)
}
return cmd
}
/***
* exec("perl xxx *.log")
*/
func ExecWithStdIO(cmdLine string) error {
cmd := exec.Command(cmdLine)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}
/***
* exeshell("del *.log")
*/
func ExecShellWithStdIO(cmdLine string) error {
var cmd *exec.Cmd
if runtime.GOOS == "windows" {
cmd = exec.Command("cmd", "/C", cmdLine)
} else {
cmd = exec.Command(cmd_exe_bin, "-c", cmdLine)
}
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}
func ExecShellOutput(cmd string) (err error, str string) {
var sb strings.Builder
var errsb strings.Builder
e1 := ExecShellWithIO(cmd, nil, &sb, &errsb)
if e1 != nil {
return fmt.Errorf("异常:%s, 错误输出:%s", e1.Error(), errsb.String()), ""
} else {
return nil, sb.String()
}
}
/*
*
sb := NewBytesBuilder()
ExecShellWithIO("dir c:\\*.*", nil, sb, sb)
sb.StatusString();
*/
func ExecShellWithIO(cmdLine string, rd io.Reader, outstd, outerr io.Writer) error {
var cmd *exec.Cmd
if runtime.GOOS == "windows" {
cmd = exec.Command("cmd", "/C", cmdLine)
} else {
cmd = exec.Command(cmd_exe_bin, "-c", cmdLine)
}
if rd != nil {
cmd.Stdin = rd
}
cmd.Stdout = outstd
cmd.Stderr = outerr
return cmd.Run()
}
func ExecShellAndNoWait(cmdLine string) error {
var cmd *exec.Cmd
if runtime.GOOS == "windows" {
cmd = exec.Command("cmd", "/C", cmdLine)
} else {
cmd = exec.Command(cmd_exe_bin, "-c", cmdLine)
}
return cmd.Start()
}
/**
* 如果filename存在,
* 尝试对filename进行重命名, 然后创建一个新的file
* 如果重命名失败,则使用一个新的文件名
*/
func TryCreateFileAndRenameIfFileExists(fileName string) (newfile *os.File, ret_err error) {
err := ForceCreateFilePath(fileName)
if err != nil {
return nil, err
}
// 如果文件存在则尝试改名
if FileIsExists(fileName) {
strNewName := GetNewFileUseIncSN(fileName)
err := RenameFile(fileName, strNewName)
if err != nil {
ret_err = err
}
}
// 如果文件还是存在,就使用新的文件
f, _, err := CreateIfExistsThenRename(fileName) // 如果重命名旧文件失败,就用新文件
if err != nil {
return nil, err
}
newfile = f
return
}
func CreateRewrite(fileName string) (*os.File, error) {
return os.OpenFile(fileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
}
func RewriteFile(fileName string, fileData []byte) error {
return os.WriteFile(fileName, fileData, 0666)
}
func RewriteFileFunc(fileName string, fn func(w *os.File) error) error {
f, err := os.OpenFile(fileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil {
return err
}
defer f.Close()
return fn(f)
}
func ReadPerLineFile(filename string, offset int64, cb func(idx int64, line []byte) bool) (int64, error) {
var readf *os.File
var err error
defer func() {
if readf != nil {
readf.Close()
}
}()
readf, err = os.Open(filename)
if err != nil {
return 0, err
}
if offset > 0 {
readf.Seek(offset, 0)
}
return ReadPerLine(readf, cb)
}
func ReadPerLine(reader io.Reader, cb func(idx int64, line []byte) bool) (int64, error) {
br := bufio.NewReaderSize(reader, 1096)
index := int64(0)
for {
lineBuf, _, err := br.ReadLine()
if err == io.EOF {
break
}
if err != nil {
return index, err
}
if !cb(index, lineBuf) {
break
}
index++
}
return index, nil
}
func ReadPerLineEx(reader io.Reader, cb func(idx int64, line []byte) bool) (int64, error) {
br := bufio.NewReaderSize(reader, 4096)
index := int64(0)
lineBuf := make([]byte, 0, 8192)
for {
tmpBuf, isPrefix, err := br.ReadLine()
if err == io.EOF {
if len(lineBuf) > 0 {
cb(index, lineBuf)
}
break
}
if err != nil {
if len(lineBuf) > 0 {
cb(index, lineBuf)
}
return index, err
}
lineBuf = append(lineBuf, tmpBuf...)
if !isPrefix {
if !cb(index, lineBuf) {
break
}
index++
lineBuf = lineBuf[:0]
}
}
return index, nil
}
/***
*/
func ReadFileBlockBufOffset(fileName string, offset int64, cb func(block []byte) bool, makebuffunc func() []byte) (int64, error) {
var readf *os.File
var err error
defer func() {
if readf != nil {
readf.Close()
}
}()
readf, err = os.Open(fileName)
if err != nil {
return 0, err
}
if offset > 0 {
readf.Seek(offset, 0)
}
br := bufio.NewReader(readf)
n := int64(0)
for {
buf := makebuffunc()
l, err := br.Read(buf)
if err == io.EOF {
break
}
if err != nil {
return n, err
}
if !cb(buf[:l]) {
break
}
n += int64(l)
}
return n, nil
}
/***
*/
func ReadFileBlockBuf(fileName string, cb func(block []byte) bool, makebuffunc func() []byte) (int64, error) {
return ReadFileBlockBufOffset(fileName, 0, cb, makebuffunc)
}
func SplitStrWidth(s string, width int) (rval []string) {
sr := strings.NewReader(s)
val := make([]byte, width)
for {
n, err := sr.Read(val)
if err != nil {
break
}
rval = append(rval, string(val[:n]))
}
return
}
/***
* 依次读取行, 执行cb函数
* cb函数如果返回false则中断读取, idx从0开始
* 返回读取行数和错误
*/
func ReadFileLine(fileName string, cb func(idx int64, line []byte) bool) (int64, error) {
var readf *os.File
var err error
defer func() {
if readf != nil {
readf.Close()
}
}()
readf, err = os.Open(fileName)
if err != nil {
return 0, err
}
return ReadPerLineEx(readf, cb)
}
func InsertBeforeLineFile(fileName string, idx_before_line int64, fileData []byte) error {
var old, newf *os.File
var err error
defer func() {
if old != nil {
old.Close()
}
if newf != nil {
newf.Close()
}
}()
old, err = os.Open(fileName)
if err != nil {
return err
}
strNewFn := fileName + ".tmp"
newf, err = os.OpenFile(strNewFn, os.O_RDWR|os.O_CREATE, 0766)
if err != nil {
return err
}
defer newf.Close()
br := bufio.NewReader(old)
index := int64(1)
for {
if idx_before_line == index {
_, err = newf.Write(fileData)
if err != nil {
return err
}
}
strLine, _, err := br.ReadLine()
if err == io.EOF {
break
}
if err != nil {
return err
}
_, err = newf.WriteString(string(strLine) + "\n")
if err != nil {
return err
}
index++
}
old.Close()
old = nil
newf.Close()
newf = nil
os.Remove(fileName)
os.Rename(strNewFn, fileName)
return nil
}
/*
*
- srcFile : 存的文件
dataFile 数据文件
将dataFile 加入到srcFile中去
*/
func AppendAllFile(srcFile string, dataFile string) error {
var srcF, dataF *os.File
var err error
defer func() {
if srcF != nil {
srcF.Close()
}
if dataF != nil {
dataF.Close()
}
}()
dataF, err = os.Open(dataFile)
if err != nil {
return err
}
srcF, err = os.OpenFile(srcFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
return err
}
//dataR := bufio.NewReader(dataF);
cacheBuf := make([]byte, 4096)
for {
n, err := dataF.Read(cacheBuf)
if err == io.EOF {
break
} else if err != nil {
return err
}
_, err = srcF.Write(cacheBuf[:n])
if err != nil {
return err
}
}
return nil
}
func NewFileFromReader(fileName string, reader io.Reader) (int, error) {
fl, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil {
return 0, err
}
defer fl.Close()
cacheBuf := make([]byte, 1024)
ncounter := 0
for {
n, err := reader.Read(cacheBuf)
if err == io.EOF {
return ncounter, nil
}
if err != nil {
return ncounter, err
}
n, err = fl.Write(cacheBuf[:n])
if err != nil {
return ncounter, err
}
ncounter += n
}
return ncounter, nil
}
func NewFileData(fileName string, fileData []byte) (int, error) {
fl, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil {
return 0, err
}
defer fl.Close()
n, err := fl.Write(fileData)
if err == nil && n < len(fileData) {
err = io.ErrShortWrite
}
return n, err
}
func AppendFileEx(fileName string, fileData []byte, forceDir bool) (int, error) {
if forceDir {
err := ForceCreateFilePath(fileName)
if err != nil {
return 0, err
}
}
return AppendFile(fileName, fileData)
}
func AppendFile(fileName string, fileData []byte) (int, error) {
fl, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
return 0, err
}
defer fl.Close()
n, err := fl.Write(fileData)
if err == nil && n < len(fileData) {
err = io.ErrShortWrite
}
return n, err
}
func ReadFile(fileName string) ([]byte, error) {
return os.ReadFile(fileName)
}
/*
*
获取绝对路径
*/
func GetAbsPath(basePath, relaPath string) (string, error) {
if len(basePath) == 0 {
return "", errors.New("绝对路径不可以为空")
}
basePath = strings.Replace(basePath, "\\", "/", -1)
relaPath = strings.Replace(relaPath, "\\", "/", -1)
basePath = strings.TrimSuffix(basePath, "/")
arr1 := strings.Split(basePath, "/")
arr2 := strings.Split(relaPath, "/")
depth := 0
arr2idx := 0
for i := 0; i < len(arr2); i++ {
if arr2[i] == ".." {
depth++
arr2idx++
} else if arr2[i] == "." {
arr2idx++
} else {
break
}
}
if arr2idx == 0 {
rval := strings.Join(arr2[arr2idx:], PathSeparator)
return rval, nil
}
if depth >= len(arr1) {
return "", errors.New("相对路径的层数超出了范围!")
}
rval := strings.Join(arr1[0:len(arr1)-depth], PathSeparator)
if arr2idx < len(arr2) {
rval += PathSeparator + strings.Join(arr2[arr2idx:], PathSeparator)
}
return rval, nil
}
/*
**
求两个绝对路径的相对路径
写一个函数计算出两个绝对路径(如path1 = /a/b/c/d, path2 = /a/e/f)的相对路径为 ../../e/f
*/
func GetRelativePath(basePath, path2 string) (string, error) {
if basePath == "" || path2 == "" {
return "", errors.New("绝对路径不可以为空")
}
basePath = strings.Replace(basePath, "\\", "/", -1)
path2 = strings.Replace(path2, "\\", "/", -1)
arr1 := strings.Split(basePath[1:], "/")
arr2 := strings.Split(path2[1:], "/")
depth := 0
for i := 0; i < len(arr1) && i < len(arr2); i++ {
if arr1[i] == arr2[i] {
depth++
} else {
break
}
}
prefix := ""
if len(arr1)-depth-1 <= 0 {
prefix = "./"
} else {
for i := len(arr1) - depth - 1; i > 0; i-- {
prefix += "../"
}
}
fmt.Println(depth)
if len(arr2)-depth > 0 {
prefix += strings.Join(arr2[depth:], "/")
}
return prefix, nil
}
func CombineFilePath(parts ...string) string {
s := strings.Builder{}
i := 0
for _, v := range parts {
if len(v) > 0 {
if i > 0 {
s.WriteString(PathSeparator)
}
s.WriteString(v)
i++
}
}
return s.String()
}
/*
**
0: 不存在
1: 文件
2: 目录
*/
func FileIs(fileName string) int {
if fi, _ := os.Stat(fileName); fi != nil {
if fi.IsDir() {
return 2
} else {
return 1
}
} else {
return 0
}
}
// exists returns whether the given file or directory exists or not
func FileIsExists(fileName string) bool {
if _, err := os.Stat(fileName); err != nil {
if os.IsNotExist(err) {
// file does not exist
} else {
// other error
}
return false
} else {
//exist
return true
}
}
/*
*
XXXX.dat -> XXX.1.dat(XXX.2.dat)
*/
func GetNewFileUseIncSN(fileName string) string {
rval := fileName
sn := 0
var basePath string
var fileExt string
var baseName string
basePath = ExtractFilePath(fileName) + "/"
fileExt = path.Ext(fileName)
baseName = ExtractFileNameWithOutPathAndExt(fileName)
for {
sn++
rval = basePath + baseName + fmt.Sprintf(".%d%s", sn, fileExt)
if !FileIsExists(rval) {
return rval
}
}
}
func FileNameAddfix(fileName, prefix, suffix string) string {
basePath, baseName := Split2PathAndFileName(fileName)
fileExt := path.Ext(baseName)
baseName = strings.TrimSuffix(baseName, fileExt)
if len(prefix) > 0 {
baseName = prefix + baseName
}
if len(suffix) > 0 {
baseName = baseName + suffix
}
return basePath + baseName + fileExt
}
func RenameFile(afile string, newFileName string) error {
return os.Rename(afile, newFileName)
}
func NewFileNameIfExistsThenIncSN(fileName string) string {
rval := fileName
sn := 0
var basePath string
var fileExt string
var baseName string
for {
if !FileIsExists(rval) {
return rval
}
if len(basePath) == 0 {
basePath = ExtractFilePath(fileName) + "/"
fileExt = path.Ext(fileName)
baseName = ExtractFileNameWithOutPathAndExt(fileName)
}
sn++
rval = basePath + baseName + fmt.Sprintf(".%d%s", sn, fileExt)
}
}
func CreateIfExistsThenRename(name string) (*os.File, string, error) {
itry := 0
for {
newFileName := NewFileNameIfExistsThenIncSN(name)
f, err := os.Create(newFileName)
if err != nil {
if itry > 5 {
return nil, "", err
}
itry++
continue
}
return f, newFileName, nil
}
}
func MD5SumFile(filePath string) string {
const fileChunk = 8192 // 8KB
file, err := os.Open(filePath)
if err != nil {
return err.Error()
}
defer file.Close()
info, _ := file.Stat()
fileSize := info.Size()
blocks := uint64(math.Ceil(float64(fileSize) / float64(fileChunk)))
hash := md5.New()
for i := uint64(0); i < blocks; i++ {
blockSize := int(math.Min(fileChunk, float64(fileSize-int64(i*fileChunk))))
buf := make([]byte, blockSize)
file.Read(buf)
hash.Write(buf)
//io.Write(hash, string(buf))
}
return fmt.Sprintf("%x", hash.Sum(nil))
}
type ReadFileSession struct {
closeflag int8
errflag int8
file *os.File
filename string
}
func NewReadFileSession(filename string) *ReadFileSession {
return &ReadFileSession{filename: filename}
}
func (this *ReadFileSession) Reset() {
this.Close()
this.file = nil
this.closeflag = 0
this.errflag = 0
}
func (this *ReadFileSession) Close() error {
f0 := this.file
if f0 != nil {
return f0.Close()
}
this.closeflag = 1
return io.ErrClosedPipe
}
func (this *ReadFileSession) CloseFlag() int8 {
return this.closeflag
}
func (this *ReadFileSession) ErrFlag() int8 {
return this.errflag
}
func (this *ReadFileSession) Read(b []byte) (n int, err error) {
if this.file == nil {
file, err := os.Open(this.filename)
if err != nil {
this.errflag = 1
return -1, err
}
this.file = file
}
n, err = this.file.Read(b)
if err != nil {
this.errflag = 1
}
return
}
var (
panic_logpath string
panic_fileprefix string
panic_idx int32
)
func EnablePanicRecordFile(logpath string) {
GoFunCatchException = true
OnCatchAllPanic = PanicRecordFile
exeName := os.Args[0] //获取程序名称
exeName = ExtractFileNameWithOutPathAndExt(exeName)
panic_logpath = logpath
if len(panic_logpath) > 0 {
if panic_logpath[len(panic_logpath)-1] == '/' || panic_logpath[len(panic_logpath)-1] == '\\' {
} else {
panic_logpath = fmt.Sprintf("%s%s", panic_logpath, PathSeparator)
}
ForceCreatePath(panic_logpath)
}
panic_fileprefix = fmt.Sprintf("%s%s-%d-dump", panic_logpath, exeName, os.Getpid())
}
func PanicRecordFile(err interface{}, args ...interface{}) {
now := time.Now() //获取当前时间
uid := atomic.AddInt32(&panic_idx, 1)
datestr := now.Format("20060102")
nowstrEx := now.Format("2006-01-02 15:04:05.999")
//设定时间格式
fname := fmt.Sprintf("%s-%s-%d.log", panic_fileprefix, datestr, uid) //保存错误信息文件名:程序名-进程ID-当前时间(年月日时分秒)
datastr := ""
if len(args) > 0 {
if str, ok := args[0].(string); ok {
datastr = str
} else if fn, ok := args[0].(func() interface{}); ok {
v0 := fn()
datastr, _ = v0.(string)
}
}
f, err2 := os.OpenFile(fname, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0660)
if err2 != nil {
fmt.Fprintln(os.Stderr, "存储异常文件失败:", err2)
fmt.Fprintln(os.Stderr, "捕捉到的异常:", err)
if len(datastr) > 0 {
fmt.Fprintf(os.Stderr, "%s\r\n", datastr)
}
fmt.Fprintf(os.Stderr, "[%s]异常堆栈信息:%s\r\n", nowstrEx, string(debug.Stack())) //输出堆栈信息
return
}
defer f.Close()
fmt.Println("存储异常到文件: ", fname)
if len(datastr) > 0 {
f.WriteString(fmt.Sprintf("%s\r\n", datastr))
}
f.WriteString(fmt.Sprintf("[%s]:%v\r\n", nowstrEx, err)) //输出panic信息
f.WriteString("---------------------------------------------\r\n")
f.WriteString(string(debug.Stack())) //输出堆栈信息
}
func init() {
if runtime.GOOS == "windows" {
PathSeparator = "\\"
cmd_exe_bin = "cmd"
} else {
if FileIsExists("/bin/bash") {
cmd_exe_bin = "/bin/bash"
} else {
cmd_exe_bin = "/bin/sh"
}
PathSeparator = "/"
}
RootPath, _ = GetCurrentDirectory()
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/ymofen/gobase.git
git@gitee.com:ymofen/gobase.git
ymofen
gobase
gobase
v1.2.24053

搜索帮助

344bd9b3 5694891 D2dac590 5694891