Skip to content

BaseFile

The interface shared by File and RawFile.

Every operation on a closed file raises StateError.

A file is an Io, so a function such as zip.open can use it, starting at its current position, without closing it.

Inherits from: io.Io

Methods

acl … -> (security.AnyAcl | nil)

Gets the ACL stored on the open file.

Parameters

NameTypeDescription
:kind? (:POSIX: | :NFS4: | :MACOS:) ACL format to query. Defaults to :POSIX:.
:default? Bool Query the directory's inheritable default ACL.

Returns

The matching portable ACL type, depending on kind, or nil when no ACL metadata is stored.

close()

Closes the file, first writing out pending writes.

The file is closed even if writing them out fails. This is required if open was not given a block. Closing a file that is already closed does nothing.

Example

let file = open data.txt
let data = file.read_str()
file.close()

copy_data dst … -> Int

The method form of fs.copy_data.

Parameters

NameTypeDescription
dst BaseFile Handle to write to.
:range? Range[Int] Absolute byte region of the source.
:size? Int Number of bytes to take from the source cursor.
:offset? Int Absolute byte offset in the destination.
:clone? CloneMode How blocks should be shared between the source and destination. Defaults to :AUTO:.

fs_metadata() -> (fs.unix.FsMetadata | fs.windows.FsMetadata)

Gets filesystem metadata for the filesystem backing the open file.

Example

open data.txt r do |file|
  let meta = file.fs_metadata()
  echo "Available: $(meta.available)"

lock[R] range func … -> R

Acquires a byte-range lock while func runs.

Parameters

NameTypeDescription
range Range[Int] Half-open byte range; .. is the whole file.
func ((FileLock) -> R) Block receiving a FileLock.
:shared? Bool Acquire a shared rather than exclusive lock.

Returns

The block's result.

The lock is exclusive unless shared is true. It is released before the method returns, including when the block raises an error or is canceled.

Locks are mandatory on Windows, where they prevent conflicting file access. On Unix they are advisory and affect only programs that cooperate through file locking.

Waiting for a conflicting lock cannot be canceled, and a canceled strand may delay the program's exit until the lock is acquired. Use try_lock for bounded or cancellable waiting.

Overlapping active lock ranges on the same file are unsupported, including identical shared ranges.

Finite zero-length ranges are invalid on Unix. On Windows they conflict only with positive-length ranges that start before and end after their offset. They do not conflict with another zero-length range or a range starting at the same offset. The zero-length range 0..0 is invalid.

Example

file.lock (0..128) do |lock|
  update_header()

metadata() -> (fs.unix.Metadata | fs.windows.Metadata)

Gets metadata for the open file.

Example

open data.txt r do |file|
  let meta = file.metadata()
  echo "Size: $(meta.size)"
  echo "Modified: $(meta.modified)"

read … -> Bin

Reads bytes from the file.

Parameters

NameTypeDescription
size? Int Number of bytes to read. Without it, reads to the end of the file.
:offset? Int Byte offset to read from. Without it, reads at the cursor and advances it.
size

size bytes are read however many transfers that takes; a shorter result means the end of the file was reached, and reading entirely past the end gives an empty result rather than an error.

:offset

A positional read leaves the cursor where it was, so it can be used alongside streaming reads on the same handle, and several regions of a file can be read without seeking between them.

Because a positional read touches nothing shared, any number of them may be in flight on one handle at once — several strands can read different regions of the same open file concurrently. Streaming reads still take the handle exclusively, since they move the cursor.

Example

# Read a specific number of bytes
open data.bin do |file|
  let header = file.read 4
  let rest = file.read()

# Read a record without moving the cursor
open data.bin do |file|
  let record = file.read 64 offset: (index * 64)

remove_xattr name …

Removes an extended attribute.

Parameters

NameTypeDescription
name (Str | XattrEntry) Attribute name or entry from xattrs.
:namespace? XattrNamespace Namespace to update.

Example

open data.txt r+ do |file|
  file.remove_xattr "comment"

sec_desc … -> security.windows.SecDesc

Gets selected parts of the Windows security descriptor through this file's existing handle.

The operation raises sys.PermissionDeniedError if the file was opened without the necessary Windows access rights. Other platforms raise sys.UnsupportedError.

Parameters

NameTypeDescription
:owner? Bool Load the owner SID. Defaults to true.
:group? Bool Load the primary group SID. Defaults to true.
:dacl? Bool Load the discretionary ACL. Defaults to true.
:sacl? Bool Load the system ACL. Defaults to false.

seek … -> Int

Moves the file cursor.

Parameters

NameTypeDescription
offset? Int Byte offset relative to the current position.
:start? Int Absolute byte offset from the start of the file.
:end? Int Byte offset relative to the end of the file.

Returns

The new absolute byte position.

Example

open data.bin r do |file|
  file.seek start: 10   # absolute
  file.seek 10          # relative to the cursor
  file.seek (0 - 4)     # backwards
  file.seek end: (0 - 1)  # relative to the end

set_acl acl …

Sets or removes an ACL on the open file.

A built ACL supplies its format and must match an explicit kind:. An untyped sequence of declarative ACE dictionaries requires kind:. With nil, the omitted kind remains POSIX.

Parameters

NameTypeDescription
acl (security.AclSpec | nil) ACL or declarative ACE sequence.
:kind? (:POSIX: | :NFS4: | :MACOS:) Required for an untyped ACL specification.
:default? Bool Update the directory's inheritable default ACL.

set_size size

Truncates the file to the given byte length.

Parameters

NameTypeDescription
size Int New file length in bytes.

Example

open data.bin r+ do |file|
  file.set_size 8

set_xattr name value …

Sets an extended attribute value.

On Windows, empty values are rejected. NTFS deletes the attribute instead of storing an empty value.

Parameters

NameTypeDescription
name (Str | XattrEntry) Attribute name or entry from xattrs.
value (Str | Bin) Attribute bytes; strings use UTF-8.
:namespace? XattrNamespace Namespace to update.

Example

open data.txt r+ do |file|
  file.set_xattr "comment" "ready"

streams() -> Iter[fs.windows.StreamEntry]

Lists alternate data streams for this file.

Windows only.

Example

let path = Path data.txt
open $path r do |file|
  for stream = file.streams()
    echo (path / stream)

sync …

Flushes the file to durable storage, returning once the device reports it committed.

Parameters

NameTypeDescription
:data? Bool Flush data only, skipping unneeded metadata. See fs.sync for what this selects and what a flush does and does not guarantee.

Example

open journal.bin w do |file|
  file.write $entry
  file.sync()

tell() -> Int

Returns the current cursor position in bytes.

For a File, this is the logical position, where the next read or write happens.

Example

open data.txt r do |file|
  assert_eq (file.tell()) 0
  file.read 5
  assert_eq (file.tell()) 5

try_lock[R] range func … -> R

Attempts to acquire a byte-range lock without waiting.

Parameters

NameTypeDescription
range Range[Int] Half-open byte range; .. is the whole file.
func ((FileLock) -> R) Block receiving a FileLock.
:shared? Bool Acquire a shared rather than exclusive lock.

Returns

The block's result.

The block always runs. lock.held is false when another handle holds a conflicting lock. Other acquisition failures raise errors.

Example

file.try_lock (..) do |lock|
  if lock.held
    update_index()

update_sec_desc ...options …

Applies the components selected by a security descriptor's mask through this file's existing handle.

The operation raises sys.PermissionDeniedError if the file was opened without the necessary Windows access rights. Windows may normalize the resulting descriptor. Other platforms raise sys.UnsupportedError.

Parameters

NameTypeDescription
desc? security.windows.SecDescSpec Descriptor to apply.
...options security.windows.SecDescOptions Components and control flags, instead of or alongside desc.

write *data … -> Int

Writes data to the file, given in pieces.

All of data is written, however many transfers that takes. With offset:, the pieces go to consecutive offsets.

Parameters

NameTypeDescription
:offset? Int Byte offset to write at. Without it, writes at the cursor and advances it.
*data (Str | Bin) Data to write. Strings are written as UTF-8 text.
:offset

A positional write leaves the cursor where it was, so it can be used alongside streaming writes on the same handle, and several regions of a file can be written without seeking between them. Writing past the end extends the file, zero-filling the gap.

As with read, any number of positional writes may be in flight on one handle at once.

Returns

The number of bytes written.

Errors

Exception Condition
StateError offset: on a file opened for appending

An append handle writes at the end of the file no matter what offset the platform is given, so an explicit one cannot be honored rather than merely being unimplemented.

Example

open output.txt w do |file|
  let bytes_written = file.write "Hello, World!"
  echo "Wrote $bytes_written bytes"
  file.write $line "\n"

# Patch a record in place without disturbing the cursor
open data.bin r+ do |file|
  file.write $record offset: (index * 64)

xattr name … -> Bin

Gets an extended attribute value.

Parameters

NameTypeDescription
name (Str | XattrEntry) Attribute name or entry from xattrs.
:namespace? XattrNamespace Namespace to query.

Example

open data.txt r do |file|
  let value = file.xattr "comment"

xattrs … -> Iter[XattrEntry]

Lists extended attributes for this file.

On Windows, this uses NTFS extended attributes. Returned names may differ in case from the requested name.

Parameters

NameTypeDescription
:namespace? (XattrNamespace | :ANY:) Namespace to query; :ANY: lists all namespaces.

Example

open data.txt r do |file|
  for attr = file.xattrs()
    echo $attr.name