1 Star 1 Fork 0

D10.天地弦 / gobase

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
file.go 29.17 KB
一键复制 编辑 原始数据 按行查看 历史
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424
package gobase
import (
"bufio"
"crypto/md5"
"errors"
"fmt"
"io"
"io/ioutil"
"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 ioutil.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()
}
1
https://gitee.com/ymofen/gobase.git
git@gitee.com:ymofen/gobase.git
ymofen
gobase
gobase
v1.2.24052

搜索帮助

53164aa7 5694891 3bd8fe86 5694891