getFileSize and setFileSize procedures for File and AsyncFile
Platform independent procedure to set a file length. Useful when replacing file content.
This commit is contained in:
parent
4ba6f9808e
commit
bc5c2d8414
4 changed files with 34 additions and 5 deletions
|
|
@ -70,14 +70,16 @@ else:
|
||||||
result = O_RDWR
|
result = O_RDWR
|
||||||
result = result or O_NONBLOCK
|
result = result or O_NONBLOCK
|
||||||
|
|
||||||
proc getFileSize(f: AsyncFile): int64 =
|
proc getFileSize*(f: AsyncFile): int64 =
|
||||||
## Retrieves the specified file's size.
|
## Retrieves the specified file's size.
|
||||||
when defined(windows) or defined(nimdoc):
|
when defined(windows) or defined(nimdoc):
|
||||||
var high: DWord
|
var high: DWord
|
||||||
let low = getFileSize(f.fd.Handle, addr high)
|
let low = getFileSize(f.fd.Handle, addr high)
|
||||||
if low == INVALID_FILE_SIZE:
|
if low == INVALID_FILE_SIZE:
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
return (high shl 32) or low
|
result = (high shl 32) or low
|
||||||
|
else:
|
||||||
|
result = lseek(f.fd.cint, 0, SEEK_END)
|
||||||
|
|
||||||
proc openAsync*(filename: string, mode = fmRead): AsyncFile =
|
proc openAsync*(filename: string, mode = fmRead): AsyncFile =
|
||||||
## Opens a file specified by the path in ``filename`` using
|
## Opens a file specified by the path in ``filename`` using
|
||||||
|
|
@ -466,6 +468,22 @@ proc write*(f: AsyncFile, data: string): Future[void] =
|
||||||
addWrite(f.fd, cb)
|
addWrite(f.fd, cb)
|
||||||
return retFuture
|
return retFuture
|
||||||
|
|
||||||
|
proc setFileSize*(f: AsyncFile, length: int64) =
|
||||||
|
## Set a file length.
|
||||||
|
when defined(windows) or defined(nimdoc):
|
||||||
|
var
|
||||||
|
high = (length shr 32).Dword
|
||||||
|
let
|
||||||
|
low = (length and 0xffffffff).Dword
|
||||||
|
status = setFilePointer(f.fd.Handle, low, addr high, 0)
|
||||||
|
lastErr = osLastError()
|
||||||
|
if (status == INVALID_SET_FILE_POINTER and lastErr.int32 != NO_ERROR) or
|
||||||
|
(setEndOfFile(f.fd.Handle) == 0):
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
else:
|
||||||
|
if ftruncate(f.fd.cint, length) == -1:
|
||||||
|
raiseOSError(osLastError())
|
||||||
|
|
||||||
proc close*(f: AsyncFile) =
|
proc close*(f: AsyncFile) =
|
||||||
## Closes the file specified.
|
## Closes the file specified.
|
||||||
unregister(f.fd)
|
unregister(f.fd)
|
||||||
|
|
@ -498,4 +516,4 @@ proc readToStream*(f: AsyncFile, fs: FutureStream[string]) {.async.} =
|
||||||
break
|
break
|
||||||
await fs.write(data)
|
await fs.write(data)
|
||||||
|
|
||||||
fs.complete()
|
fs.complete()
|
||||||
|
|
|
||||||
|
|
@ -2895,6 +2895,9 @@ when not defined(JS): #and not defined(nimscript):
|
||||||
proc getFileSize*(f: File): int64 {.tags: [ReadIOEffect], benign.}
|
proc getFileSize*(f: File): int64 {.tags: [ReadIOEffect], benign.}
|
||||||
## retrieves the file size (in bytes) of `f`.
|
## retrieves the file size (in bytes) of `f`.
|
||||||
|
|
||||||
|
proc setFileSize*(f: File, size: int64) {.tags: [ReadIOEffect], benign.}
|
||||||
|
## changes the size of file `f` (in bytes).
|
||||||
|
|
||||||
proc readBytes*(f: File, a: var openArray[int8|uint8], start, len: Natural): int {.
|
proc readBytes*(f: File, a: var openArray[int8|uint8], start, len: Natural): int {.
|
||||||
tags: [ReadIOEffect], benign.}
|
tags: [ReadIOEffect], benign.}
|
||||||
## reads `len` bytes into the buffer `a` starting at ``a[start]``. Returns
|
## reads `len` bytes into the buffer `a` starting at ``a[start]``. Returns
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,8 @@ proc c_ferror(f: File): cint {.
|
||||||
importc: "ferror", header: "<stdio.h>", tags: [].}
|
importc: "ferror", header: "<stdio.h>", tags: [].}
|
||||||
proc c_setvbuf(f: File, buf: pointer, mode: cint, size: csize): cint {.
|
proc c_setvbuf(f: File, buf: pointer, mode: cint, size: csize): cint {.
|
||||||
importc: "setvbuf", header: "<stdio.h>", tags: [].}
|
importc: "setvbuf", header: "<stdio.h>", tags: [].}
|
||||||
|
proc c_ftruncate(f: FileHandle, len: clong): cint {.
|
||||||
|
importc: "ftruncate", header: "<unistd.h>".}
|
||||||
|
|
||||||
proc raiseEIO(msg: string) {.noinline, noreturn.} =
|
proc raiseEIO(msg: string) {.noinline, noreturn.} =
|
||||||
sysFatal(IOError, msg)
|
sysFatal(IOError, msg)
|
||||||
|
|
@ -373,6 +375,11 @@ proc getFileSize(f: File): int64 =
|
||||||
result = getFilePos(f)
|
result = getFilePos(f)
|
||||||
setFilePos(f, oldPos)
|
setFilePos(f, oldPos)
|
||||||
|
|
||||||
|
proc setFileSize(f: File, size: int64) =
|
||||||
|
## Set a file length.
|
||||||
|
if c_ftruncate(getFileHandle f, size.clong) == -1:
|
||||||
|
raiseEIO("cannot truncate file")
|
||||||
|
|
||||||
proc readFile(filename: string): TaintedString =
|
proc readFile(filename: string): TaintedString =
|
||||||
var f: File
|
var f: File
|
||||||
if open(f, filename):
|
if open(f, filename):
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,10 @@ proc main() {.async.} =
|
||||||
# Simple write/read test.
|
# Simple write/read test.
|
||||||
block:
|
block:
|
||||||
var file = openAsync(fn, fmReadWrite)
|
var file = openAsync(fn, fmReadWrite)
|
||||||
await file.write("test")
|
await file.write("testing")
|
||||||
file.setFilePos(0)
|
file.setFilePos(0)
|
||||||
await file.write("foo")
|
await file.write("foo")
|
||||||
|
file.setFileSize(4)
|
||||||
file.setFilePos(0)
|
file.setFilePos(0)
|
||||||
let data = await file.readAll()
|
let data = await file.readAll()
|
||||||
doAssert data == "foot"
|
doAssert data == "foot"
|
||||||
|
|
@ -24,7 +25,7 @@ proc main() {.async.} =
|
||||||
var file = openAsync(fn, fmAppend)
|
var file = openAsync(fn, fmAppend)
|
||||||
await file.write("\ntest2")
|
await file.write("\ntest2")
|
||||||
let errorTest = file.readAll()
|
let errorTest = file.readAll()
|
||||||
echo await errorTest
|
yield errorTest
|
||||||
doAssert errorTest.failed
|
doAssert errorTest.failed
|
||||||
file.close()
|
file.close()
|
||||||
file = openAsync(fn, fmRead)
|
file = openAsync(fn, fmRead)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue