222 lines
5.5 KiB
Go
222 lines
5.5 KiB
Go
package file
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"io/ioutil"
|
||
"os"
|
||
"os/user"
|
||
"path/filepath"
|
||
"strings"
|
||
|
||
"github.com/gofrs/flock"
|
||
)
|
||
|
||
//Получить текущую рабочую папку
|
||
// 0.1.0
|
||
func GetCWD() string {
|
||
wd, e := os.Getwd()
|
||
if e != nil {
|
||
return ""
|
||
}
|
||
return wd
|
||
}
|
||
|
||
//Получить имя исполняемого файла
|
||
// 0.1.0
|
||
func GetBinName() string {
|
||
bn, e := os.Executable()
|
||
if e != nil {
|
||
return ""
|
||
}
|
||
return filepath.Base(bn)
|
||
}
|
||
|
||
//Получить папку исполняемого файла
|
||
// 0.1.0
|
||
func GetBinDir() string {
|
||
bn, e := os.Executable()
|
||
if e != nil {
|
||
return ""
|
||
}
|
||
return filepath.Dir(bn)
|
||
}
|
||
|
||
//Получить домашнюю папку
|
||
// 0.1.0
|
||
func GetHome() string {
|
||
u, e := user.Current()
|
||
if e != nil {
|
||
return ""
|
||
}
|
||
return u.HomeDir
|
||
}
|
||
|
||
//Развернуть путь до полного
|
||
// 0.1.0
|
||
//Префиксы:
|
||
// "." - заменяется папкой исполняемого файла
|
||
// "~" - заменяется домашней папкой пользователя
|
||
// "/" - замен не производится
|
||
// "" - дополняется текущей рабочей папкой
|
||
func RealPath(path string) string {
|
||
if len(path) < 1 {
|
||
return GetCWD()
|
||
}
|
||
switch path[0] {
|
||
case '.':
|
||
return GetBinDir() + "/" + strings.TrimLeft(path, "./")
|
||
case '~':
|
||
return GetHome() + "/" + strings.TrimLeft(path, "~/")
|
||
case '/':
|
||
return path
|
||
default:
|
||
return GetCWD() + "/" + path
|
||
}
|
||
}
|
||
|
||
//Получить расширение файла
|
||
// 0.1.1
|
||
func Ext(file string) string {
|
||
fpa := strings.Split(file, "/")
|
||
fa := strings.Split(fpa[len(fpa)-1], ".")
|
||
if len(fa) < 2 {
|
||
return ""
|
||
}
|
||
return fa[len(fa)-1]
|
||
}
|
||
|
||
//Существует ли файл
|
||
// 0.1.0
|
||
func Exists(file string) bool {
|
||
if _, e := os.Stat(RealPath(file)); os.IsNotExist(e) {
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
|
||
//Загрузить файл
|
||
// 0.2.0
|
||
func Load(file string) ([]byte, error) {
|
||
if !Exists(file) {
|
||
//return nil, errs.RaiseError(ErrFileNotFound, "File '"+file+"' not found")
|
||
return nil, fmt.Errorf("file not found: %s", file)
|
||
}
|
||
ret, e := ioutil.ReadFile(RealPath(file))
|
||
if e != nil {
|
||
//return nil, errs.RaiseError(ErrFileRead, "Error read file '"+file+"': "+e.Error())
|
||
return nil, fmt.Errorf("error read file '%s': %v", file, e)
|
||
}
|
||
return ret, nil
|
||
}
|
||
|
||
//Загрузить и распарсить JSON-файл
|
||
// 0.2.0
|
||
func LoadJSON(file string) (data interface{}, err error) {
|
||
src, err := Load(file)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
e := json.Unmarshal(src, &data)
|
||
if e != nil {
|
||
//return nil, errs.RaiseError(ErrParseJSON, "Error parse file '"+file+"': "+e.Error())
|
||
return nil, fmt.Errorf("error parse file '%s': %v", file, e)
|
||
}
|
||
return
|
||
}
|
||
|
||
//Сохранить файл, создать путь если не существует
|
||
// 0.2.0
|
||
func Save(file string, data []byte, perms ...os.FileMode) error {
|
||
fName := RealPath(file)
|
||
fPath := filepath.Dir(fName)
|
||
pa := getPerms(perms)
|
||
if e := os.MkdirAll(fPath, pa[1]); e != nil {
|
||
//return errs.RaiseError(ErrCreatePath, "Error create path '"+fPath+"': "+e.Error())
|
||
return fmt.Errorf("error create path '%s': %v", fPath, e)
|
||
}
|
||
if e := os.WriteFile(fName, data, pa[0]); e != nil {
|
||
//return errs.RaiseError(ErrFileWrite, "Error write file '"+fName+"': "+e.Error())
|
||
return fmt.Errorf("error write file '%s': %v", file, e)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
//Разобрать массив прав
|
||
// 0.1.3
|
||
func getPerms(perms []os.FileMode) (pa []os.FileMode) {
|
||
pa = make([]os.FileMode, 0)
|
||
if len(perms) > 0 {
|
||
pa = append(pa, perms[0])
|
||
} else {
|
||
pa = append(pa, 0664)
|
||
}
|
||
if len(perms) > 1 {
|
||
pa = append(pa, perms[1])
|
||
} else {
|
||
pa = append(pa, 0775)
|
||
}
|
||
return pa
|
||
}
|
||
|
||
//Добавить в файл, создать если не существует
|
||
// 0.2.0
|
||
func Append(file string, data []byte, perms ...os.FileMode) error {
|
||
fName := RealPath(file)
|
||
f, err := OpenCreate(fName, os.O_CREATE|os.O_APPEND|os.O_WRONLY, perms...)
|
||
if err != nil {
|
||
//return errs.UpError(err)
|
||
return err
|
||
}
|
||
defer f.Close()
|
||
lock := flock.New(fName)
|
||
if e := lock.Lock(); err != nil {
|
||
//return errs.RaiseError(ErrFileLock, e.Error())
|
||
return fmt.Errorf("error lock file '%s': %v", fName, e)
|
||
}
|
||
defer lock.Unlock()
|
||
f.Write(data)
|
||
return nil
|
||
}
|
||
|
||
//Сохранить JSON-файл
|
||
// 0.2.0
|
||
func SaveJSON(file string, data interface{}, perms ...os.FileMode) error {
|
||
jsonData, e := json.Marshal(data)
|
||
if e != nil {
|
||
//return errs.RaiseError(ErrParseJSON, "Error parse data for file '"+file+"': "+e.Error())
|
||
return fmt.Errorf("error marshal data for file '%s': %v", file, e)
|
||
}
|
||
return Save(file, jsonData, perms...)
|
||
}
|
||
|
||
//Удалить файл
|
||
// 0.2.0
|
||
func Delete(file string) error {
|
||
if e := os.Remove(RealPath(file)); e != nil {
|
||
//return errs.RaiseError(ErrFileDelete, "Error delete file '"+file+"': "+e.Error())
|
||
return fmt.Errorf("error delete file '%s': %v", RealPath(file), e)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
//Открыть файл, создать если не существует, вместе с путем
|
||
// 0.2.0
|
||
func OpenCreate(file string, flag int, perms ...os.FileMode) (*os.File, error) {
|
||
pa := getPerms(perms)
|
||
fn := RealPath(file)
|
||
fp := filepath.Dir(fn)
|
||
if !Exists(fn) {
|
||
if e := os.MkdirAll(fp, pa[1]); e != nil {
|
||
//return nil, errs.RaiseError(ErrCreatePath, "Error create path: '"+fp+"': "+e.Error())
|
||
return nil, fmt.Errorf("error create path '%s': %v", fp, e)
|
||
}
|
||
}
|
||
f, e := os.OpenFile(fn, flag, pa[0])
|
||
if e != nil {
|
||
//return nil, errs.RaiseError(ErrFileOpen, "Error create file: '"+fn+"': "+e.Error())
|
||
return nil, fmt.Errorf("error create file '%s': %v", fn, e)
|
||
}
|
||
return f, nil
|
||
}
|