mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-18 21:40:32 +00:00
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:
@@ -70,14 +70,16 @@ else:
|
||||
result = O_RDWR
|
||||
result = result or O_NONBLOCK
|
||||
|
||||
proc getFileSize(f: AsyncFile): int64 =
|
||||
proc getFileSize*(f: AsyncFile): int64 =
|
||||
## Retrieves the specified file's size.
|
||||
when defined(windows) or defined(nimdoc):
|
||||
var high: DWord
|
||||
let low = getFileSize(f.fd.Handle, addr high)
|
||||
if low == INVALID_FILE_SIZE:
|
||||
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 =
|
||||
## 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)
|
||||
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) =
|
||||
## Closes the file specified.
|
||||
unregister(f.fd)
|
||||
@@ -498,4 +516,4 @@ proc readToStream*(f: AsyncFile, fs: FutureStream[string]) {.async.} =
|
||||
break
|
||||
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.}
|
||||
## 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 {.
|
||||
tags: [ReadIOEffect], benign.}
|
||||
## 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: [].}
|
||||
proc c_setvbuf(f: File, buf: pointer, mode: cint, size: csize): cint {.
|
||||
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.} =
|
||||
sysFatal(IOError, msg)
|
||||
@@ -373,6 +375,11 @@ proc getFileSize(f: File): int64 =
|
||||
result = getFilePos(f)
|
||||
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 =
|
||||
var f: File
|
||||
if open(f, filename):
|
||||
|
||||
@@ -11,9 +11,10 @@ proc main() {.async.} =
|
||||
# Simple write/read test.
|
||||
block:
|
||||
var file = openAsync(fn, fmReadWrite)
|
||||
await file.write("test")
|
||||
await file.write("testing")
|
||||
file.setFilePos(0)
|
||||
await file.write("foo")
|
||||
file.setFileSize(4)
|
||||
file.setFilePos(0)
|
||||
let data = await file.readAll()
|
||||
doAssert data == "foot"
|
||||
@@ -24,7 +25,7 @@ proc main() {.async.} =
|
||||
var file = openAsync(fn, fmAppend)
|
||||
await file.write("\ntest2")
|
||||
let errorTest = file.readAll()
|
||||
echo await errorTest
|
||||
yield errorTest
|
||||
doAssert errorTest.failed
|
||||
file.close()
|
||||
file = openAsync(fn, fmRead)
|
||||
|
||||
Reference in New Issue
Block a user