代码拉取完成,页面将自动刷新
package u2
import (
"log"
"os"
"strings"
"sync"
"time"
)
// FileHandle 封装文件句柄和定时器
type FileHandle struct {
file *os.File
timer *time.Timer
}
var (
fileMap = sync.Map{} // 存储文件句柄的并发安全map
mu sync.Mutex // 保护文件操作的互斥锁
)
// AppendFile 追加内容到指定文件,自动管理文件句柄
//
// 参数:
// - filename: 目标文件名
// - content: 要追加的内容
//
// 返回值:
// - error: 操作过程中发生的错误
//
// 注意:
//
// 文件句柄会在1秒不活动后自动关闭,如果写入失败会重试3次
func AppendFile(filename, content string) error {
mu.Lock()
defer mu.Unlock()
var handle *FileHandle
handle2, ok := fileMap.Load(filename)
if !ok {
file, err := os.OpenFile(filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
if err != nil {
log.Println("open file error:", err)
return err
}
handle = &FileHandle{
file: file,
timer: time.AfterFunc(1*time.Second, func() {
mu.Lock()
defer mu.Unlock()
fileMap.Delete(filename)
file.Close()
}),
}
fileMap.Store(filename, handle)
} else {
handle = handle2.(*FileHandle)
}
_, err := handle.file.WriteString(content)
if err != nil {
if strings.Contains(err.Error(), "write after close") ||
strings.Contains(err.Error(), "file already closed") {
return AppendFileWithTimes(filename, content, 3)
}
log.Println("write file error:", err)
return err
}
return nil
}
// AppendFileWithTimes 带重试机制的追加文件操作
//
// 参数:
// - filename: 目标文件名
// - content: 要追加的内容
// - times: 最大重试次数
//
// 返回值:
// - error: 操作过程中发生的错误
func AppendFileWithTimes(filename, content string, times int) error {
var err error
for i := 0; i < times; i++ {
err = AppendFile(filename, content)
if err == nil {
break
}
}
return err
}
// CloseAllFiles 关闭所有打开的文件句柄
//
// 注意:
//
// 通常在程序退出时调用,确保所有文件资源被正确释放
func CloseAllFiles() {
fileMap.Range(func(key, value interface{}) bool {
filename := key.(string)
fileMap.Delete(filename)
handle := value.(*FileHandle)
handle.timer.Stop()
handle.file.Close()
return true
})
}
// AppendFileOnce 一次性追加内容到文件,不保持文件句柄
//
// 参数:
// - filename: 目标文件名
// - content: 要追加的内容
func AppendFileOnce(filename, content string) {
file, err := os.OpenFile(filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
if err != nil {
log.Println("open file error:", err)
return
}
defer file.Close()
if _, err := file.WriteString(content); err != nil {
log.Println("write file error:", err)
}
}
// ReadFileLine 逐行读取文件内容,调用回调函数处理每一行
//
// 参数:
// - filename: 要读取的文件名
// - callback: 处理每一行的回调函数
func ReadFileLine(filename string, callback func(line string)) {
file, err := os.Open(filename)
if err != nil {
log.Println("open file error:", err)
return
}
defer file.Close()
buf := make([]byte, 1024)
var line string
for {
n, err := file.Read(buf)
if err != nil {
if err.Error() == "EOF" {
if line != "" {
callback(line)
}
break
}
log.Println("read file error:", err)
return
}
if n == 0 {
if line != "" {
callback(line)
}
break
}
for i := 0; i < n; i++ {
if buf[i] == '\n' {
callback(line)
line = ""
} else {
line += string(buf[i])
}
}
}
}
// ReadFile 读取整个文件内容
//
// 参数:
// - filename: 要读取的文件名
//
// 返回值:
// - []byte: 文件内容,如果读取失败返回nil
func ReadFile(filename string) []byte {
b, err := os.ReadFile(filename)
if err != nil {
log.Println("read file error:", err)
return nil
}
return b
}
// ReadFileStringSlice 将文件内容按指定分隔符分割成字符串切片
//
// 参数:
// - filename: 要读取的文件名
// - seq: 分隔符,默认为换行符
//
// 返回值:
// - []string: 分割后的字符串切片
func ReadFileStringSlice(filename string, seq string) []string {
b := ReadFile(filename)
if b == nil {
return make([]string, 0)
}
if seq == "" {
seq = "\n"
}
return strings.Split(string(b), seq)
}
// RemoveFile 如果文件存在则删除
//
// 参数:
// - filename: 要删除的文件名
//
// 返回值:
// - error: 操作过程中发生的错误
func RemoveFile(filename string) error {
if _, err := os.Stat(filename); err == nil {
return os.Remove(filename)
}
return nil
}
// ExistFile 检查文件是否存在
//
// 参数:
// - filename: 要检查的文件名
//
// 返回值:
// - bool: 文件存在返回true,否则返回false
func ExistFile(filename string) bool {
_, err := os.Stat(filename)
return err == nil
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。