File
public struct File: not Copyable { /* private fields */ }RAII-owned POSIX file handle.
The wrapped file descriptor is closed automatically when the File
goes out of scope, so explicit close is never necessary. File is
not Copyable to keep the descriptor uniquely owned — pass by
reference or move it instead. Conforms to both Readable and Writable,
although calls fail with EBADF if the open mode does not permit the
direction (e.g. writing to a file opened with open()).
Examples
// Readable whole file in 4 KiB chunks.
var file = try File.open("input.txt");
var buf = Array[UInt8](repeating: 0, count: 4096);
while true {
let n = try file.read(into: buf.asSlice());
if n == 0 { break }
// process buf[0..n]
}
Representation
One libc.Fd (32-bit signed integer) field.
Memory Model
Owning, unique. The deinit calls close(fd) if fd >= 0; close
errors are silently ignored — there's no caller to surface them to.
Properties
var fd: libc.Fd
var fd: libc.FdInitializers
init(libc.Fd)
init(libc.Fd)Internal init wrapping a raw descriptor; not for general use.
Methods
public static func create(String) -> Result[File, IoError]
public static func create(String) -> Result[File, IoError]Creates (or truncates) path for writing with mode 0644.
Existing contents are discarded.
Examples
var file = try File.create("output.txt");
try writeString(file, "New content");public static func createNew(String) -> Result[File, IoError]
public static func createNew(String) -> Result[File, IoError]Creates a new file, failing if the path already exists. The canonical pattern for cooperative locking via lockfiles.
Errors
Returns Err carrying EEXIST if the path already exists.
Examples
match File.createNew("lock.pid") {
.Ok(f) => /* we hold the lock */ holdLock(f),
.Err(e) => /* somebody else has it */ retryLater()
}public static func open(String) -> Result[File, IoError]
public static func open(String) -> Result[File, IoError]Opens an existing file for reading. The file must exist; missing
paths surface as Err(IoError.last()) carrying ENOENT, and
permission failures as EACCES.
public static func openAppend(String) -> Result[File, IoError]
public static func openAppend(String) -> Result[File, IoError]Opens (or creates) a file in append mode. Every write atomically
lands at the current end of file regardless of where seek last
left the cursor — the standard idiom for log files and any
concurrent appender.
public static func openReadWrite(String) -> Result[File, IoError]
public static func openReadWrite(String) -> Result[File, IoError]Opens an existing file for both reading and writing. Use for
in-place modification of a file that already exists; for "create
or open" semantics combine with create / createNew as
appropriate.
public mutating func position() -> Result[Int64, IoError]
public mutating func position() -> Result[Int64, IoError]Convenience for seek(.Current(0)).
public func rawFd() -> libc.Fd
public func rawFd() -> libc.FdReturns the underlying libc file descriptor for direct FFI use.
Ownership stays with the File; do not call close on the
returned value or the deinit will hit EBADF.
public mutating func rewind() -> Result[(), IoError]
public mutating func rewind() -> Result[(), IoError]Convenience for seek(.Start(0)) that drops the returned offset.
public mutating func seek(to: Seek) -> Result[Int64, IoError]
public mutating func seek(to: Seek) -> Result[Int64, IoError]Calls lseek(2) with the requested anchor and offset. Returns
the new absolute position from the start of the file. Seeking
past EOF is allowed; a subsequent write extends the file (with a
hole on filesystems that support sparse files).
Examples
var file = try File.openReadWrite("data.bin");
try file.seek(to: .Start(0)); // rewind
try file.seek(to: .Current(100)); // skip 100 bytes
let size = try file.seek(to: .End(0)); // size of fileImplementsReadable
Methods
public mutating func read(into: ArraySlice[UInt8]) -> Result[Int64, IoError]
public mutating func read(into: ArraySlice[UInt8]) -> Result[Int64, IoError]Calls read(2). Advances the file position by the byte count
returned. Short reads (n < buf.count) are normal — keep calling
until 0 is returned (EOF) or an error fires. Use readAll/
readExact from std.io.read when looping by hand isn't wanted.
ImplementsWritable
Methods
public mutating func flush() -> Result[(), IoError]
public mutating func flush() -> Result[(), IoError]No-op; File does no internal buffering. Reaches the kernel as
soon as write returns, but does not call fsync — durability
across power loss requires a separate, currently-unwrapped libc
call.
public mutating func write(from: ArraySlice[UInt8]) -> Result[Int64, IoError]
public mutating func write(from: ArraySlice[UInt8]) -> Result[Int64, IoError]Calls write(2). May write fewer bytes than supplied — wrap with
writeAll from std.io.write to loop until done.
Defined in lang/std/io/file.ks