//go:build windows package yu_file import ( yu_bytes "gogs.qqck.cn/s/tools/bytes" yu_sys "gogs.qqck.cn/s/tools/sys" ) // GetEx // // @Description: 独占方式(多线程安全)读文件 // @param name 文件路径 // @param start 读入起始位置 // @param size 读入字节数 func GetEx(name string, start int64, size int) (result []byte) { j_fd := Openfile(name, yu_sys.GENERIC_READ, yu_sys.FILE_SHARE_NO, yu_sys.OPEN_EXISTING, 0) if j_fd == 0 { return } defer yu_sys.CloseHandle.Call(j_fd) if start != 0 && !yu_sys.SetFilePointerEx.CallBool(j_fd, start, 0, yu_sys.FILE_BEGIN) { return } j_size, j_ok := getFileSizeEx(j_fd) if !j_ok { return } if j_size == 0 || start+int64(size) > j_size { return } return readFileSize(j_fd, size) } // SetEx // // @Description: 独占方式(多线程安全)写文件 // @param name 文件路径 // @param start 写出起始位置 // @param bufs 写出内容... func SetEx(name string, start int64, bufs ...[]byte) bool { j_fd := Openfile(name, yu_sys.GENERIC_WRITE, yu_sys.FILE_SHARE_NO, yu_sys.OPEN_ALWAYS, yu_sys.FILE_FLAG_WRITE_THROUGH) if j_fd == 0 { return false } defer yu_sys.CloseHandle.Call(j_fd) if start != 0 && !yu_sys.SetFilePointerEx.CallBool(j_fd, start, 0, yu_sys.FILE_BEGIN) { return false } for j_i := 0; j_i < len(bufs); j_i++ { if !writeFile(j_fd, bufs[j_i]) { return false } } return true } // Add // // @Description: 独占方式(多线程安全)读写文件计数已实现持久化存储计数 // @param name 文件路径 // @param start 读取位置偏移(以该位置往后8个字节为存储数据) // @param on 计算回调,传 nil 则只读取 // @return int64 最终存储结果 func Add(name string, start int64, on func(old int64) int64) int64 { j_fd := Openfile(name, yu_sys.GENERIC_READ|yu_sys.GENERIC_WRITE, yu_sys.FILE_SHARE_NO, yu_sys.OPEN_ALWAYS, yu_sys.FILE_FLAG_WRITE_THROUGH) if j_fd == 0 { return 0 } defer yu_sys.CloseHandle.Call(j_fd) if start != 0 && !yu_sys.SetFilePointerEx.CallBool(j_fd, start, 0, yu_sys.FILE_BEGIN) { return 0 } j_buf := make([]byte, 8) readFileBuf(j_fd, j_buf) j_result := int64(j_buf[0]) | int64(j_buf[1])<<8 | int64(j_buf[2])<<16 | int64(j_buf[3])<<24 | int64(j_buf[4])<<32 | int64(j_buf[5])<<40 | int64(j_buf[6])<<48 | int64(j_buf[7])<<56 if on == nil { return j_result } j_result = on(j_result) j_buf[0] = byte(j_result) j_buf[1] = byte(j_result >> 8) j_buf[2] = byte(j_result >> 16) j_buf[3] = byte(j_result >> 24) j_buf[4] = byte(j_result >> 32) j_buf[5] = byte(j_result >> 40) j_buf[6] = byte(j_result >> 48) j_buf[7] = byte(j_result >> 56) if yu_sys.SetFilePointerEx.CallBool(j_fd, 0, 0, yu_sys.FILE_BEGIN) { writeFile(j_fd, j_buf) } return j_result } const ( lines_size = 1024 * 1024 * 32 ) // ForInfo // @Description: For 数据结构体 type ForInfo struct { // Start 当前数据的读入起始位置 Start int64 // Size 当前数据的总大小,如果为 -1 则自动调用api读取实际文件大小 Size int64 // ForSize 循环的数据总大小 ForSize int64 // ForGetN 已循环次数 ForGetN int64 // ForGetMax 最多读取循环数据的次数,超过该次数后未循环的读取完毕将不再读取循环的数据,-1为不限制 ForGetMax int64 } func NewForInfo() ForInfo { return ForInfo{ Start: 0, Size: -1, ForSize: 0, ForGetN: 0, ForGetMax: 0, } } // En // // @Description: 编码数据 func (t *ForInfo) En() [40]byte { j_buf := [40]byte{} j_buf[0] = byte(t.Start) j_buf[1] = byte(t.Start >> 8) j_buf[2] = byte(t.Start >> 16) j_buf[3] = byte(t.Start >> 24) j_buf[4] = byte(t.Start >> 32) j_buf[5] = byte(t.Start >> 40) j_buf[6] = byte(t.Start >> 48) j_buf[7] = byte(t.Start >> 56) j_buf[8] = byte(t.Size) j_buf[9] = byte(t.Size >> 8) j_buf[10] = byte(t.Size >> 16) j_buf[11] = byte(t.Size >> 24) j_buf[12] = byte(t.Size >> 32) j_buf[13] = byte(t.Size >> 40) j_buf[14] = byte(t.Size >> 48) j_buf[15] = byte(t.Size >> 56) j_buf[16] = byte(t.ForSize) j_buf[17] = byte(t.ForSize >> 8) j_buf[18] = byte(t.ForSize >> 16) j_buf[19] = byte(t.ForSize >> 24) j_buf[20] = byte(t.ForSize >> 32) j_buf[21] = byte(t.ForSize >> 40) j_buf[22] = byte(t.ForSize >> 48) j_buf[23] = byte(t.ForSize >> 56) j_buf[24] = byte(t.ForGetN) j_buf[25] = byte(t.ForGetN >> 8) j_buf[26] = byte(t.ForGetN >> 16) j_buf[27] = byte(t.ForGetN >> 24) j_buf[28] = byte(t.ForGetN >> 32) j_buf[29] = byte(t.ForGetN >> 40) j_buf[30] = byte(t.ForGetN >> 48) j_buf[31] = byte(t.ForGetN >> 56) j_buf[32] = byte(t.ForGetMax) j_buf[33] = byte(t.ForGetMax >> 8) j_buf[34] = byte(t.ForGetMax >> 16) j_buf[35] = byte(t.ForGetMax >> 24) j_buf[36] = byte(t.ForGetMax >> 32) j_buf[37] = byte(t.ForGetMax >> 40) j_buf[38] = byte(t.ForGetMax >> 48) j_buf[39] = byte(t.ForGetMax >> 56) return j_buf } // De // // @Description: 解码数据 func (t *ForInfo) De(data [40]byte) { t.Start = int64(data[0]) | int64(data[1])<<8 | int64(data[2])<<16 | int64(data[3])<<24 | int64(data[4])<<32 | int64(data[5])<<40 | int64(data[6])<<48 | int64(data[7])<<56 t.Size = int64(data[8]) | int64(data[9])<<8 | int64(data[10])<<16 | int64(data[11])<<24 | int64(data[12])<<32 | int64(data[13])<<40 | int64(data[14])<<48 | int64(data[15])<<56 t.ForSize = int64(data[16]) | int64(data[17])<<8 | int64(data[18])<<16 | int64(data[19])<<24 | int64(data[20])<<32 | int64(data[21])<<40 | int64(data[22])<<48 | int64(data[23])<<56 t.ForGetN = int64(data[24]) | int64(data[25])<<8 | int64(data[26])<<16 | int64(data[27])<<24 | int64(data[28])<<32 | int64(data[29])<<40 | int64(data[30])<<48 | int64(data[31])<<56 t.ForGetMax = int64(data[32]) | int64(data[33])<<8 | int64(data[34])<<16 | int64(data[35])<<24 | int64(data[36])<<32 | int64(data[37])<<40 | int64(data[38])<<48 | int64(data[39])<<56 } // ForGet // // @Description: 独占方式(多线程安全)读取文件内容 // @param name 文件路径 // @param eof 截止标志 // @param min 最小读取字节数 // @param max 最大读取字节数 // @param seek_get ForInfo 信息获取函数 // @param seek_set ForInfo 信息更新保存函数 // @return []byte 读取内容 func ForGet(name string, eof []byte, min, max int64, seek_get func() ForInfo, seek_set func(ForInfo)) []byte { if seek_get == nil { return nil } j_fd := Openfile(name, yu_sys.GENERIC_READ, yu_sys.FILE_SHARE_NO, yu_sys.OPEN_EXISTING, 0) if j_fd == 0 { return nil } defer yu_sys.CloseHandle.Call(j_fd) j_info := seek_get() j_eof_len := int64(len(eof)) if j_info.Size < 0 && !yu_sys.GetFileSizeEx.CallBool(j_fd, &j_info.Size) { return nil } if max < min { max += min } _get: j_get_size := j_info.Size - j_info.Start if j_get_size > 0 { // ------------------------------------------------------------------------判断剩余字节数如果小于等于 max 或 eof 直接读入全部 if j_get_size <= max || j_get_size <= j_eof_len { if !yu_sys.SetFilePointerEx.CallBool(j_fd, j_info.Start, 0, yu_sys.FILE_BEGIN) { return nil } j_result := make([]byte, j_get_size) j_get_size = readFileBuf(j_fd, j_result) if seek_set != nil { j_info.Start += j_get_size seek_set(j_info) } return j_result[:j_get_size] } // ------------------------------------------------------------------------检索 eof 标志 j_result := make([]byte, j_eof_len) for { if !yu_sys.SetFilePointerEx.CallBool(j_fd, j_info.Start+min, 0, yu_sys.FILE_BEGIN) { return nil } j_get_size = readFileBuf(j_fd, j_result) if j_get_size == 0 || j_get_size < j_eof_len { return nil } if yu_bytes.Equals(j_result, eof) { break } if min++; min > max { return nil } // 到当前数据的上限了,读入失败 } if !yu_sys.SetFilePointerEx.CallBool(j_fd, j_info.Start, 0, yu_sys.FILE_BEGIN) { return nil } j_result = make([]byte, min+j_eof_len) j_get_size = readFileBuf(j_fd, j_result) if seek_set != nil { j_info.Start += j_get_size seek_set(j_info) } return j_result[:j_get_size-j_eof_len] // 删除尾部 eof 标志 } // ------------------------------------------------------------------------判断是否从循环里读取数据 if j_info.ForSize == 0 { return nil } if j_info.ForGetMax > -1 && j_info.ForGetN >= j_info.ForGetMax { return nil } j_info.Start, j_info.Size, j_info.ForSize = 0, j_info.ForSize, 0 // 重置当前数据结构 j_info.ForGetN++ goto _get } // ForPut // // @Description: 独占方式(多线程安全)写出文件内容 // @param name 文件路径 // @param seek_get ForInfo 信息获取函数 // @param seek_set ForInfo 信息更新保存函数 // @param bufs 欲写出的书... // @return bool 是否操作成功 func ForPut(name string, seek_get func() ForInfo, seek_set func(ForInfo), bufs ...[]byte) bool { if seek_get == nil { return false } j_fd := Openfile(name, yu_sys.GENERIC_READ|yu_sys.GENERIC_WRITE, yu_sys.FILE_SHARE_NO, yu_sys.OPEN_ALWAYS, yu_sys.FILE_FLAG_WRITE_THROUGH) if j_fd == 0 { return false } defer yu_sys.CloseHandle.Call(j_fd) j_info := seek_get() if j_info.Size < 0 && !yu_sys.GetFileSizeEx.CallBool(j_fd, &j_info.Size) { return false } for j_i := 0; j_i < len(bufs); j_i++ { // 判断是往循环里写数据还是在文件末尾追加数据 j_buf_len := int64(len(bufs[j_i])) if j_info.Start-j_info.ForSize > j_buf_len { // 往循环里写数据 if !yu_sys.SetFilePointerEx.CallBool(j_fd, j_info.ForSize, 0, yu_sys.FILE_BEGIN) { return false } if !writeFile(j_fd, bufs[j_i]) { return false } j_info.ForSize += j_buf_len } else { // 在文件末尾追加数据 if !yu_sys.SetFilePointerEx.CallBool(j_fd, j_info.Size, 0, yu_sys.FILE_BEGIN) { return false } if !writeFile(j_fd, bufs[j_i]) { return false } j_info.Size += j_buf_len } if seek_set != nil { seek_set(j_info) } } return true }