v1.0.7
This commit is contained in:
兔子
2023-04-12 17:07:16 +08:00
parent 09c82c311b
commit c699bc7d0c
4 changed files with 335 additions and 31 deletions

41
main.go
View File

@@ -2,4 +2,45 @@ package main
func main() { func main() {
// // 读取图片文件
// file, err := os.Open("input.jpg")
// if err != nil {
// log.Fatal(err)
// }
//
// defer file.Close()
//
// // 解码图片
// img, _, err := image.Decode(file)
// if err != nil {
// log.Fatal(err)
// }
//
// // 创建输出文件
// out, err := os.Create("output.jpg")
// if err != nil {
// log.Fatal(err)
// }
//
// defer out.Close()
//
// // 压缩图片并写入输出文件
// opts := jpeg.Options{Quality: 50} // 调整图片质量
// err = jpeg.Encode(out, img, &opts)
// if err != nil {
// log.Fatal(err)
// }
//
// fmt.Println("图片已成功压缩!")
// item := utils.File().Page(2).Limit(10).Line(dir + "\\text.log")
//
// if item.Error != nil {
// fmt.Println(item.Error)
// return
// }
//
// for key, val := range item.Slice {
// fmt.Println(key + 1, val)
// }
} }

100
text.log Normal file
View File

@@ -0,0 +1,100 @@
这是第 01行 内容
这是第 02行 内容
这是第 03行 内容
这是第 04行 内容
这是第 05行 内容
这是第 06行 内容
这是第 07行 内容
这是第 08行 内容
这是第 09行 内容
这是第 10行 内容
这是第 11行 内容
这是第 12行 内容
这是第 13行 内容
这是第 14行 内容
这是第 15行 内容
这是第 16行 内容
这是第 17行 内容
这是第 18行 内容
这是第 19行 内容
这是第 20行 内容
这是第 21行 内容
这是第 22行 内容
这是第 23行 内容
这是第 24行 内容
这是第 25行 内容
这是第 26行 内容
这是第 27行 内容
这是第 28行 内容
这是第 29行 内容
这是第 30行 内容
这是第 31行 内容
这是第 32行 内容
这是第 33行 内容
这是第 34行 内容
这是第 35行 内容
这是第 36行 内容
这是第 37行 内容
这是第 38行 内容
这是第 39行 内容
这是第 40行 内容
这是第 41行 内容
这是第 42行 内容
这是第 43行 内容
这是第 44行 内容
这是第 45行 内容
这是第 46行 内容
这是第 47行 内容
这是第 48行 内容
这是第 49行 内容
这是第 50行 内容
这是第 51行 内容
这是第 52行 内容
这是第 53行 内容
这是第 54行 内容
这是第 55行 内容
这是第 56行 内容
这是第 57行 内容
这是第 58行 内容
这是第 59行 内容
这是第 60行 内容
这是第 61行 内容
这是第 62行 内容
这是第 63行 内容
这是第 64行 内容
这是第 65行 内容
这是第 66行 内容
这是第 67行 内容
这是第 68行 内容
这是第 69行 内容
这是第 70行 内容
这是第 71行 内容
这是第 72行 内容
这是第 73行 内容
这是第 74行 内容
这是第 75行 内容
这是第 76行 内容
这是第 77行 内容
这是第 78行 内容
这是第 79行 内容
这是第 80行 内容
这是第 81行 内容
这是第 82行 内容
这是第 83行 内容
这是第 84行 内容
这是第 85行 内容
这是第 86行 内容
这是第 87行 内容
这是第 88行 内容
这是第 89行 内容
这是第 90行 内容
这是第 91行 内容
这是第 92行 内容
这是第 93行 内容
这是第 94行 内容
这是第 95行 内容
这是第 96行 内容
这是第 97行 内容
这是第 98行 内容
这是第 99行 内容
这是第 100行 内容

View File

@@ -1,13 +1,22 @@
package utils package utils
import ( import (
"bufio"
"errors" "errors"
"github.com/spf13/cast" "github.com/spf13/cast"
"io" "io"
"os" "os"
"path/filepath" "path/filepath"
"sync"
) )
// FileStruct - File 结构体
type FileStruct struct {
request *FileRequest
response *FileResponse
}
// FileRequest - File 请求
type FileRequest struct { type FileRequest struct {
// 文件名 // 文件名
Name string Name string
@@ -17,27 +26,37 @@ type FileRequest struct {
Dir string Dir string
// 文件后缀 // 文件后缀
Ext string Ext string
// 限制行数
Limit int
// 读取偏移量
Page int
} }
// FileStruct - File 结构体 // FileResponse - File 响应
type FileStruct struct {
request *FileRequest
response *FileResponse
}
type FileResponse struct { type FileResponse struct {
Error error Error error
Result string Result any
Text string
Byte []byte Byte []byte
Slice []any Slice []any
} }
// File - 文件系统
func File(request ...FileRequest) *FileStruct { func File(request ...FileRequest) *FileStruct {
if len(request) == 0 { if len(request) == 0 {
request = append(request, FileRequest{}) request = append(request, FileRequest{})
} }
if IsEmpty(request[0].Limit) {
request[0].Limit = 10
}
if IsEmpty(request[0].Page) {
request[0].Page = 1
}
return &FileStruct{ return &FileStruct{
request : &request[0], request : &request[0],
response: &FileResponse{}, response: &FileResponse{},
@@ -68,6 +87,18 @@ func (this *FileStruct) Ext(ext any) *FileStruct {
return this return this
} }
// Limit 设置限制行数
func (this *FileStruct) Limit(limit any) *FileStruct {
this.request.Limit = cast.ToInt(limit)
return this
}
// Page 设置读取偏移量
func (this *FileStruct) Page(page any) *FileStruct {
this.request.Page = cast.ToInt(page)
return this
}
// Save 保存文件 // Save 保存文件
func (this *FileStruct) Save(reader io.Reader, path ...string) (result *FileResponse) { func (this *FileStruct) Save(reader io.Reader, path ...string) (result *FileResponse) {
@@ -80,9 +111,7 @@ func (this *FileStruct) Save(reader io.Reader, path ...string) (result *FileResp
return this.response return this.response
} }
filePath := cast.ToString(path) dir := filepath.Dir(this.request.Path)
dir := filepath.Dir(filePath)
if _, err := os.Stat(dir); os.IsNotExist(err) { if _, err := os.Stat(dir); os.IsNotExist(err) {
// 目录不存在,需要创建 // 目录不存在,需要创建
if err := os.MkdirAll(dir, 0755); err != nil { if err := os.MkdirAll(dir, 0755); err != nil {
@@ -92,7 +121,7 @@ func (this *FileStruct) Save(reader io.Reader, path ...string) (result *FileResp
} }
// 创建文件 // 创建文件
file, err := os.Create(filePath) file, err := os.Create(this.request.Path)
if err != nil { if err != nil {
this.response.Error = err this.response.Error = err
return this.response return this.response
@@ -114,7 +143,7 @@ func (this *FileStruct) Save(reader io.Reader, path ...string) (result *FileResp
return this.response return this.response
} }
return nil return this.response
} }
// Byte 获取文件字节 // Byte 获取文件字节
@@ -142,33 +171,51 @@ func (this *FileStruct) Byte(path ...any) (result *FileResponse) {
} }
}(file) }(file)
// // 获取文件大小 // 获取文件信息
// info, _ := file.Stat() info, err := file.Stat()
// size := info.Size()
// // 读取文件
// data := make([]byte, size)
// file.Read(data)
// return data
var bytes []byte
// 分批次读取
buf := make([]byte, 1024)
for {
line, err := file.Read(buf)
if err != nil { if err != nil {
this.response.Error = err
return this.response
}
size := info.Size()
// 小于50MB整体读取
if size < 50 * 1024 * 1024 {
bytes := make([]byte, size)
_, err = file.Read(bytes)
if err != nil {
this.response.Error = err
return this.response
}
this.response.Byte = bytes
this.response.Text = string(bytes)
this.response.Result = bytes
return this.response
}
// 大于等于50MB分块读取
var bytes []byte
buffer := make([]byte, 1024 * 1024)
for {
index, err := file.Read(buffer)
if err != nil && err != io.EOF {
this.response.Error = err
break
}
bytes = append(bytes, buffer[:index]...)
if err == io.EOF {
break break
} }
bytes = append(bytes, buf[:line]...)
} }
this.response.Byte = bytes this.response.Byte = bytes
this.response.Result = string(bytes) this.response.Text = string(bytes)
this.response.Result = bytes
return this.response return this.response
} }
// FileList 获取指定目录下的所有文件 // List 获取指定目录下的所有文件
func (this *FileStruct) List(opt ...map[string]any) (result *FileResponse) { func (this *FileStruct) List(opt ...map[string]any) (result *FileResponse) {
// 默认参数 // 默认参数
@@ -245,3 +292,119 @@ func (this *FileStruct) List(opt ...map[string]any) (result *FileResponse) {
this.response.Slice = cast.ToSlice(slice) this.response.Slice = cast.ToSlice(slice)
return this.response return this.response
} }
// IsExist 判断文件是否存在
func (this *FileStruct) IsExist(path ...any) (ok bool) {
if len(path) != 0 {
this.request.Path = cast.ToString(path[0])
}
if IsEmpty(this.request.Path) {
return false
}
// 判断文件是否存在
if _, err := os.Stat(this.request.Path); os.IsNotExist(err) {
return false
}
return true
}
// Line 按行读取文件
func (this *FileStruct) Line(path ...any) (result *FileResponse) {
if len(path) != 0 {
this.request.Path = cast.ToString(path[0])
}
if IsEmpty(this.request.Path) {
this.response.Error = errors.New("文件路径不能为空")
return this.response
}
// 读取块
readBlock := func(file *os.File, start int, end int) ([]string, error) {
lines := make([]string, 0)
scanner := bufio.NewScanner(file)
// 移动扫描器到指定的起始行
for i := 1; i < start && scanner.Scan(); i++ {}
// 开始读取需要的行
for i := start; i <= end && scanner.Scan(); i++ {
// 只把需要的行保存到切片中
if i >= start && i <= end {
lines = append(lines, scanner.Text())
}
}
if err := scanner.Err(); err != nil {
return nil, err
}
return lines, nil
}
file, err := os.Open(this.request.Path)
if err != nil {
this.response.Error = err
return this.response
}
defer func(file *os.File) {
err := file.Close()
if err != nil {
return
}
}(file)
end := this.request.Page * this.request.Limit
start := end - this.request.Limit + 1
lines := make([]string, 0)
// 计算每个块的大小以10MB为一个块
blockSize := 10 * 1024 * 1024
numBlocks := (end - start + 1) / blockSize
if (end - start + 1) % blockSize != 0 {
numBlocks++
}
// 并发读取每个块
var wg sync.WaitGroup
wg.Add(numBlocks)
for i := 0; i < numBlocks; i++ {
go func(i int) {
startLine := start + i * blockSize
endLine := startLine + blockSize - 1
if endLine > end {
endLine = end
}
blockLines, err := readBlock(file, startLine, endLine)
if err != nil {
this.response.Error = err
return
} else {
lines = append(lines, blockLines...)
}
wg.Done()
}(i)
}
wg.Wait()
this.response.Result = lines
this.response.Text = JsonEncode(this.response.Result)
this.response.Byte = []byte(this.response.Text)
for _, v := range lines {
this.response.Slice = append(this.response.Slice, v)
}
return this.response
}

View File

@@ -41,14 +41,14 @@ func (this *LangModel) Value(key any, args ...any) (result any) {
text := cast.ToString(key) text := cast.ToString(key)
// 解析语言包 // 解析语言包
lang := cast.ToStringMap(JsonDecode(bytes.Result)) lang := cast.ToStringMap(JsonDecode(bytes.Text))
// 获取语言 // 获取语言
result = lang[text] result = lang[text]
// 如果没有找到语言通过javascript风格获取 // 如果没有找到语言通过javascript风格获取
if IsEmpty(result) { if IsEmpty(result) {
item, err := JsonGet(bytes.Result, text) item, err := JsonGet(bytes.Text, text)
if err == nil { if err == nil {
result = item result = item
} }