extend_windows.go 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. //go:build windows
  2. package yu_file
  3. import (
  4. yu_bytes "gogs.qqck.cn/s/tools/bytes"
  5. yu_sys "gogs.qqck.cn/s/tools/sys"
  6. )
  7. // GetEx
  8. //
  9. // @Description: 独占方式(多线程安全)读文件
  10. // @param name 文件路径
  11. // @param start 读入起始位置
  12. // @param size 读入字节数
  13. func GetEx(name string, start int64, size int) (result []byte) {
  14. j_fd := Openfile(name, yu_sys.GENERIC_READ, yu_sys.FILE_SHARE_NO, yu_sys.OPEN_EXISTING, 0)
  15. if j_fd == 0 {
  16. return
  17. }
  18. defer yu_sys.CloseHandle.Call(j_fd)
  19. if start != 0 && !yu_sys.SetFilePointerEx.CallBool(j_fd, start, 0, yu_sys.FILE_BEGIN) {
  20. return
  21. }
  22. j_size, j_ok := getFileSizeEx(j_fd)
  23. if !j_ok {
  24. return
  25. }
  26. if j_size == 0 || start+int64(size) > j_size {
  27. return
  28. }
  29. return readFileSize(j_fd, size)
  30. }
  31. // SetEx
  32. //
  33. // @Description: 独占方式(多线程安全)写文件
  34. // @param name 文件路径
  35. // @param start 写出起始位置
  36. // @param bufs 写出内容...
  37. func SetEx(name string, start int64, bufs ...[]byte) bool {
  38. j_fd := Openfile(name, yu_sys.GENERIC_WRITE, yu_sys.FILE_SHARE_NO, yu_sys.OPEN_ALWAYS, yu_sys.FILE_FLAG_WRITE_THROUGH)
  39. if j_fd == 0 {
  40. return false
  41. }
  42. defer yu_sys.CloseHandle.Call(j_fd)
  43. if start != 0 && !yu_sys.SetFilePointerEx.CallBool(j_fd, start, 0, yu_sys.FILE_BEGIN) {
  44. return false
  45. }
  46. for j_i := 0; j_i < len(bufs); j_i++ {
  47. if !writeFile(j_fd, bufs[j_i]) {
  48. return false
  49. }
  50. }
  51. return true
  52. }
  53. // Add
  54. //
  55. // @Description: 独占方式(多线程安全)读写文件计数已实现持久化存储计数
  56. // @param name 文件路径
  57. // @param start 读取位置偏移(以该位置往后8个字节为存储数据)
  58. // @param on 计算回调,传 nil 则只读取
  59. // @return int64 最终存储结果
  60. func Add(name string, start int64, on func(old int64) int64) int64 {
  61. 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)
  62. if j_fd == 0 {
  63. return 0
  64. }
  65. defer yu_sys.CloseHandle.Call(j_fd)
  66. if start != 0 && !yu_sys.SetFilePointerEx.CallBool(j_fd, start, 0, yu_sys.FILE_BEGIN) {
  67. return 0
  68. }
  69. j_buf := make([]byte, 8)
  70. readFileBuf(j_fd, j_buf)
  71. j_result := int64(j_buf[0]) | int64(j_buf[1])<<8 |
  72. int64(j_buf[2])<<16 | int64(j_buf[3])<<24 |
  73. int64(j_buf[4])<<32 | int64(j_buf[5])<<40 |
  74. int64(j_buf[6])<<48 | int64(j_buf[7])<<56
  75. if on == nil {
  76. return j_result
  77. }
  78. j_result = on(j_result)
  79. j_buf[0] = byte(j_result)
  80. j_buf[1] = byte(j_result >> 8)
  81. j_buf[2] = byte(j_result >> 16)
  82. j_buf[3] = byte(j_result >> 24)
  83. j_buf[4] = byte(j_result >> 32)
  84. j_buf[5] = byte(j_result >> 40)
  85. j_buf[6] = byte(j_result >> 48)
  86. j_buf[7] = byte(j_result >> 56)
  87. if yu_sys.SetFilePointerEx.CallBool(j_fd, 0, 0, yu_sys.FILE_BEGIN) {
  88. writeFile(j_fd, j_buf)
  89. }
  90. return j_result
  91. }
  92. const (
  93. lines_size = 1024 * 1024 * 32
  94. )
  95. // ForInfo
  96. // @Description: For 数据结构体
  97. type ForInfo struct {
  98. // Start 当前数据的读入起始位置
  99. Start int64
  100. // Size 当前数据的总大小,如果为 -1 则自动调用api读取实际文件大小
  101. Size int64
  102. // ForSize 循环的数据总大小
  103. ForSize int64
  104. // ForGetN 已循环次数
  105. ForGetN int64
  106. // ForGetMax 最多读取循环数据的次数,超过该次数后未循环的读取完毕将不再读取循环的数据,-1为不限制
  107. ForGetMax int64
  108. }
  109. func NewForInfo() ForInfo {
  110. return ForInfo{
  111. Start: 0,
  112. Size: -1,
  113. ForSize: 0,
  114. ForGetN: 0,
  115. ForGetMax: 0,
  116. }
  117. }
  118. // En
  119. //
  120. // @Description: 编码数据
  121. func (t *ForInfo) En() [40]byte {
  122. j_buf := [40]byte{}
  123. j_buf[0] = byte(t.Start)
  124. j_buf[1] = byte(t.Start >> 8)
  125. j_buf[2] = byte(t.Start >> 16)
  126. j_buf[3] = byte(t.Start >> 24)
  127. j_buf[4] = byte(t.Start >> 32)
  128. j_buf[5] = byte(t.Start >> 40)
  129. j_buf[6] = byte(t.Start >> 48)
  130. j_buf[7] = byte(t.Start >> 56)
  131. j_buf[8] = byte(t.Size)
  132. j_buf[9] = byte(t.Size >> 8)
  133. j_buf[10] = byte(t.Size >> 16)
  134. j_buf[11] = byte(t.Size >> 24)
  135. j_buf[12] = byte(t.Size >> 32)
  136. j_buf[13] = byte(t.Size >> 40)
  137. j_buf[14] = byte(t.Size >> 48)
  138. j_buf[15] = byte(t.Size >> 56)
  139. j_buf[16] = byte(t.ForSize)
  140. j_buf[17] = byte(t.ForSize >> 8)
  141. j_buf[18] = byte(t.ForSize >> 16)
  142. j_buf[19] = byte(t.ForSize >> 24)
  143. j_buf[20] = byte(t.ForSize >> 32)
  144. j_buf[21] = byte(t.ForSize >> 40)
  145. j_buf[22] = byte(t.ForSize >> 48)
  146. j_buf[23] = byte(t.ForSize >> 56)
  147. j_buf[24] = byte(t.ForGetN)
  148. j_buf[25] = byte(t.ForGetN >> 8)
  149. j_buf[26] = byte(t.ForGetN >> 16)
  150. j_buf[27] = byte(t.ForGetN >> 24)
  151. j_buf[28] = byte(t.ForGetN >> 32)
  152. j_buf[29] = byte(t.ForGetN >> 40)
  153. j_buf[30] = byte(t.ForGetN >> 48)
  154. j_buf[31] = byte(t.ForGetN >> 56)
  155. j_buf[32] = byte(t.ForGetMax)
  156. j_buf[33] = byte(t.ForGetMax >> 8)
  157. j_buf[34] = byte(t.ForGetMax >> 16)
  158. j_buf[35] = byte(t.ForGetMax >> 24)
  159. j_buf[36] = byte(t.ForGetMax >> 32)
  160. j_buf[37] = byte(t.ForGetMax >> 40)
  161. j_buf[38] = byte(t.ForGetMax >> 48)
  162. j_buf[39] = byte(t.ForGetMax >> 56)
  163. return j_buf
  164. }
  165. // De
  166. //
  167. // @Description: 解码数据
  168. func (t *ForInfo) De(data [40]byte) {
  169. t.Start = int64(data[0]) | int64(data[1])<<8 | int64(data[2])<<16 | int64(data[3])<<24 |
  170. int64(data[4])<<32 | int64(data[5])<<40 | int64(data[6])<<48 | int64(data[7])<<56
  171. t.Size = int64(data[8]) | int64(data[9])<<8 | int64(data[10])<<16 | int64(data[11])<<24 |
  172. int64(data[12])<<32 | int64(data[13])<<40 | int64(data[14])<<48 | int64(data[15])<<56
  173. t.ForSize = int64(data[16]) | int64(data[17])<<8 | int64(data[18])<<16 | int64(data[19])<<24 |
  174. int64(data[20])<<32 | int64(data[21])<<40 | int64(data[22])<<48 | int64(data[23])<<56
  175. t.ForGetN = int64(data[24]) | int64(data[25])<<8 | int64(data[26])<<16 | int64(data[27])<<24 |
  176. int64(data[28])<<32 | int64(data[29])<<40 | int64(data[30])<<48 | int64(data[31])<<56
  177. t.ForGetMax = int64(data[32]) | int64(data[33])<<8 | int64(data[34])<<16 | int64(data[35])<<24 |
  178. int64(data[36])<<32 | int64(data[37])<<40 | int64(data[38])<<48 | int64(data[39])<<56
  179. }
  180. // ForGet
  181. //
  182. // @Description: 独占方式(多线程安全)读取文件内容
  183. // @param name 文件路径
  184. // @param eof 截止标志
  185. // @param min 最小读取字节数
  186. // @param max 最大读取字节数
  187. // @param seek_get ForInfo 信息获取函数
  188. // @param seek_set ForInfo 信息更新保存函数
  189. // @return []byte 读取内容
  190. func ForGet(name string, eof []byte, min, max int64, seek_get func() ForInfo, seek_set func(ForInfo)) []byte {
  191. if seek_get == nil {
  192. return nil
  193. }
  194. j_fd := Openfile(name, yu_sys.GENERIC_READ, yu_sys.FILE_SHARE_NO, yu_sys.OPEN_EXISTING, 0)
  195. if j_fd == 0 {
  196. return nil
  197. }
  198. defer yu_sys.CloseHandle.Call(j_fd)
  199. j_info := seek_get()
  200. j_eof_len := int64(len(eof))
  201. if j_info.Size < 0 && !yu_sys.GetFileSizeEx.CallBool(j_fd, &j_info.Size) {
  202. return nil
  203. }
  204. if max < min {
  205. max += min
  206. }
  207. _get:
  208. j_get_size := j_info.Size - j_info.Start
  209. if j_get_size > 0 {
  210. // ------------------------------------------------------------------------判断剩余字节数如果小于等于 max 或 eof 直接读入全部
  211. if j_get_size <= max || j_get_size <= j_eof_len {
  212. if !yu_sys.SetFilePointerEx.CallBool(j_fd, j_info.Start, 0, yu_sys.FILE_BEGIN) {
  213. return nil
  214. }
  215. j_result := make([]byte, j_get_size)
  216. j_get_size = readFileBuf(j_fd, j_result)
  217. if seek_set != nil {
  218. j_info.Start += j_get_size
  219. seek_set(j_info)
  220. }
  221. return j_result[:j_get_size]
  222. }
  223. // ------------------------------------------------------------------------检索 eof 标志
  224. j_result := make([]byte, j_eof_len)
  225. for {
  226. if !yu_sys.SetFilePointerEx.CallBool(j_fd, j_info.Start+min, 0, yu_sys.FILE_BEGIN) {
  227. return nil
  228. }
  229. j_get_size = readFileBuf(j_fd, j_result)
  230. if j_get_size == 0 || j_get_size < j_eof_len {
  231. return nil
  232. }
  233. if yu_bytes.Equals(j_result, eof) {
  234. break
  235. }
  236. if min++; min > max {
  237. return nil
  238. } // 到当前数据的上限了,读入失败
  239. }
  240. if !yu_sys.SetFilePointerEx.CallBool(j_fd, j_info.Start, 0, yu_sys.FILE_BEGIN) {
  241. return nil
  242. }
  243. j_result = make([]byte, min+j_eof_len)
  244. j_get_size = readFileBuf(j_fd, j_result)
  245. if seek_set != nil {
  246. j_info.Start += j_get_size
  247. seek_set(j_info)
  248. }
  249. return j_result[:j_get_size-j_eof_len] // 删除尾部 eof 标志
  250. }
  251. // ------------------------------------------------------------------------判断是否从循环里读取数据
  252. if j_info.ForSize == 0 {
  253. return nil
  254. }
  255. if j_info.ForGetMax > -1 && j_info.ForGetN >= j_info.ForGetMax {
  256. return nil
  257. }
  258. j_info.Start, j_info.Size, j_info.ForSize = 0, j_info.ForSize, 0 // 重置当前数据结构
  259. j_info.ForGetN++
  260. goto _get
  261. }
  262. // ForPut
  263. //
  264. // @Description: 独占方式(多线程安全)写出文件内容
  265. // @param name 文件路径
  266. // @param seek_get ForInfo 信息获取函数
  267. // @param seek_set ForInfo 信息更新保存函数
  268. // @param bufs 欲写出的书...
  269. // @return bool 是否操作成功
  270. func ForPut(name string, seek_get func() ForInfo, seek_set func(ForInfo), bufs ...[]byte) bool {
  271. if seek_get == nil {
  272. return false
  273. }
  274. 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)
  275. if j_fd == 0 {
  276. return false
  277. }
  278. defer yu_sys.CloseHandle.Call(j_fd)
  279. j_info := seek_get()
  280. if j_info.Size < 0 && !yu_sys.GetFileSizeEx.CallBool(j_fd, &j_info.Size) {
  281. return false
  282. }
  283. for j_i := 0; j_i < len(bufs); j_i++ {
  284. // 判断是往循环里写数据还是在文件末尾追加数据
  285. j_buf_len := int64(len(bufs[j_i]))
  286. if j_info.Start-j_info.ForSize > j_buf_len {
  287. // 往循环里写数据
  288. if !yu_sys.SetFilePointerEx.CallBool(j_fd, j_info.ForSize, 0, yu_sys.FILE_BEGIN) {
  289. return false
  290. }
  291. if !writeFile(j_fd, bufs[j_i]) {
  292. return false
  293. }
  294. j_info.ForSize += j_buf_len
  295. } else {
  296. // 在文件末尾追加数据
  297. if !yu_sys.SetFilePointerEx.CallBool(j_fd, j_info.Size, 0, yu_sys.FILE_BEGIN) {
  298. return false
  299. }
  300. if !writeFile(j_fd, bufs[j_i]) {
  301. return false
  302. }
  303. j_info.Size += j_buf_len
  304. }
  305. if seek_set != nil {
  306. seek_set(j_info)
  307. }
  308. }
  309. return true
  310. }