mirror of
https://gitee.com/johng/gf
synced 2026-06-07 02:12:11 +08:00
改进gfile文件内容操作为使用gfpool
This commit is contained in:
@ -7,6 +7,7 @@
|
||||
package gfile
|
||||
|
||||
import (
|
||||
"gitee.com/johng/gf/g/os/gfpool"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@ -15,8 +16,8 @@ import (
|
||||
const (
|
||||
// 方法中涉及到读取的时候的缓冲大小
|
||||
gREAD_BUFFER = 1024
|
||||
// 方法中涉及到文件指针池的默认缓存时间(秒)
|
||||
gFILE_POOL_EXPIRE = 60
|
||||
// 方法中涉及到文件指针池的默认缓存时间(毫秒)
|
||||
gFILE_POOL_EXPIRE = 60000
|
||||
)
|
||||
|
||||
// (文本)读取文件内容
|
||||
@ -43,7 +44,7 @@ func putContents(path string, data []byte, flag int, perm int) error {
|
||||
}
|
||||
}
|
||||
// 创建/打开文件
|
||||
f, err := OpenWithFlagPerm(path, flag, perm)
|
||||
f, err := gfpool.Open(path, flag, os.FileMode(perm), gFILE_POOL_EXPIRE)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -82,11 +83,11 @@ func PutBinContentsAppend(path string, content []byte) error {
|
||||
}
|
||||
|
||||
// 获得文件内容下一个指定字节的位置
|
||||
func GetNextCharOffset(file *os.File, char byte, start int64) int64 {
|
||||
func GetNextCharOffset(reader io.ReaderAt, char byte, start int64) int64 {
|
||||
buffer := make([]byte, gREAD_BUFFER)
|
||||
offset := start
|
||||
for {
|
||||
if n, err := file.ReadAt(buffer, offset); n > 0 {
|
||||
if n, err := reader.ReadAt(buffer, offset); n > 0 {
|
||||
for i := 0; i < n; i++ {
|
||||
if buffer[i] == char {
|
||||
return int64(i) + offset
|
||||
@ -102,7 +103,7 @@ func GetNextCharOffset(file *os.File, char byte, start int64) int64 {
|
||||
|
||||
// 获得文件内容下一个指定字节的位置
|
||||
func GetNextCharOffsetByPath(path string, char byte, start int64) int64 {
|
||||
if f, err := OpenWithFlagPerm(path, os.O_RDONLY, gDEFAULT_PERM); err == nil {
|
||||
if f, err := gfpool.Open(path, os.O_RDONLY, gDEFAULT_PERM, gFILE_POOL_EXPIRE); err == nil {
|
||||
defer f.Close()
|
||||
return GetNextCharOffset(f, char, start)
|
||||
} else {
|
||||
@ -112,16 +113,16 @@ func GetNextCharOffsetByPath(path string, char byte, start int64) int64 {
|
||||
}
|
||||
|
||||
// 获得文件内容直到下一个指定字节的位置(返回值包含该位置字符内容)
|
||||
func GetBinContentsTilChar(file *os.File, char byte, start int64) ([]byte, int64) {
|
||||
if offset := GetNextCharOffset(file, char, start); offset != -1 {
|
||||
return GetBinContentsByTwoOffsets(file, start, offset + 1), offset
|
||||
func GetBinContentsTilChar(reader io.ReaderAt, char byte, start int64) ([]byte, int64) {
|
||||
if offset := GetNextCharOffset(reader, char, start); offset != -1 {
|
||||
return GetBinContentsByTwoOffsets(reader, start, offset + 1), offset
|
||||
}
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
// 获得文件内容直到下一个指定字节的位置(返回值包含该位置字符内容)
|
||||
func GetBinContentsTilCharByPath(path string, char byte, start int64) ([]byte, int64) {
|
||||
if f, err := OpenWithFlagPerm(path, os.O_RDONLY, gDEFAULT_PERM); err == nil {
|
||||
if f, err := gfpool.Open(path, os.O_RDONLY, gDEFAULT_PERM, gFILE_POOL_EXPIRE); err == nil {
|
||||
defer f.Close()
|
||||
return GetBinContentsTilChar(f, char, start)
|
||||
} else {
|
||||
@ -131,9 +132,9 @@ func GetBinContentsTilCharByPath(path string, char byte, start int64) ([]byte, i
|
||||
}
|
||||
|
||||
// 获得文件内容中两个offset之间的内容 [start, end)
|
||||
func GetBinContentsByTwoOffsets(file *os.File, start int64, end int64) []byte {
|
||||
func GetBinContentsByTwoOffsets(reader io.ReaderAt, start int64, end int64) []byte {
|
||||
buffer := make([]byte, end - start)
|
||||
if _, err := file.ReadAt(buffer, start); err != nil {
|
||||
if _, err := reader.ReadAt(buffer, start); err != nil {
|
||||
return nil
|
||||
}
|
||||
return buffer
|
||||
@ -141,7 +142,7 @@ func GetBinContentsByTwoOffsets(file *os.File, start int64, end int64) []byte {
|
||||
|
||||
// 获得文件内容中两个offset之间的内容 [start, end)
|
||||
func GetBinContentsByTwoOffsetsByPath(path string, start int64, end int64) []byte {
|
||||
if f, err := OpenWithFlagPerm(path, os.O_RDONLY, gDEFAULT_PERM); err == nil {
|
||||
if f, err := gfpool.Open(path, os.O_RDONLY, gDEFAULT_PERM, gFILE_POOL_EXPIRE); err == nil {
|
||||
defer f.Close()
|
||||
return GetBinContentsByTwoOffsets(f, start, end)
|
||||
} else {
|
||||
|
||||
@ -28,7 +28,7 @@ type Pool struct {
|
||||
|
||||
// 文件指针池指针
|
||||
type File struct {
|
||||
os.File // 底层文件指针
|
||||
*os.File // 底层文件指针
|
||||
mu sync.RWMutex // 互斥锁
|
||||
pool *Pool // 所属池
|
||||
poolid int // 所属池ID,如果池ID不同表示池已经重建,那么该文件指针也应当销毁,不能重新丢到原有的池中
|
||||
@ -81,8 +81,8 @@ func newFilePool(p *Pool, path string, flag int, perm os.FileMode, expire int) *
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &File{
|
||||
File : *file,
|
||||
return &File {
|
||||
File : file,
|
||||
pool : p,
|
||||
poolid : p.id.Val(),
|
||||
flag : flag,
|
||||
@ -108,7 +108,7 @@ func (p *Pool) File() (*File, error) {
|
||||
if file, err := os.OpenFile(f.path, f.flag, f.perm); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
f.File = *file
|
||||
f.File = file
|
||||
if stat, err = f.Stat(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -127,7 +127,9 @@ func (p *Pool) File() (*File, error) {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
f.Seek(0, 0)
|
||||
if _, err := f.Seek(0, 0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if !p.inited.Set(true) {
|
||||
gfsnotify.Add(f.path, func(event *gfsnotify.Event) {
|
||||
|
||||
@ -5,17 +5,44 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
func Benchmark_os_Open_Close(b *testing.B) {
|
||||
func Benchmark_os_Open_Close_ALLFlags(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
f, _ := os.OpenFile("/tmp/bench-test", os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_APPEND, 0766)
|
||||
f, _ := os.OpenFile("/tmp/bench-test", os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_APPEND, 0666)
|
||||
f.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_gfpool_Open_Close(b *testing.B) {
|
||||
func Benchmark_gfpool_Open_Close_ALLFlags(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
f, _ := Open("/tmp/bench-test", os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_APPEND, 0766)
|
||||
f, _ := Open("/tmp/bench-test", os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_APPEND, 0666)
|
||||
f.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_os_Open_Close_RDWR(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
f, _ := os.OpenFile("/tmp/bench-test", os.O_RDWR, 0666)
|
||||
f.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_gfpool_Open_Close_RDWR(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
f, _ := Open("/tmp/bench-test", os.O_RDWR, 0666)
|
||||
f.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_os_Open_Close_RDONLY(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
f, _ := os.OpenFile("/tmp/bench-test", os.O_RDONLY, 0666)
|
||||
f.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_gfpool_Open_Close_RDONLY(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
f, _ := Open("/tmp/bench-test", os.O_RDONLY, 0666)
|
||||
f.Close()
|
||||
}
|
||||
}
|
||||
@ -2,15 +2,18 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitee.com/johng/gf/g/os/gfpool"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
for {
|
||||
stat, err := os.Stat("/home/john/temp/log")
|
||||
f, err := gfpool.Open("/home/john/temp/log", os.O_RDWR, 0666)
|
||||
fmt.Println(err)
|
||||
fmt.Println(stat.Size())
|
||||
_, err = f.WriteString("123")
|
||||
fmt.Println(err)
|
||||
//f.Close()
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user