// reference

IO Libraries

This page documents the filesystem and stream libraries shipped under lib/io. These are library classes, not core built-in classes. Load them with intern.

io/Path

Path is the filesystem-oriented wrapper for files and directories, shipped as a Nex library under lib/io/path.nex. A Path only records a path string; creating one does not touch the filesystem. Its methods are implemented on top of runtime __path_* primitives.

Loading

intern io/Path

Support

TargetSupported
JVM REPL / interpreterYes
Generated JVM codeYes

Construction

let file: Path := create Path.make("notes/today.txt")

The path may be relative or absolute. Relative paths resolve against the working directory of the running program.

Methods

MethodArgumentsReturnsDescription
makepath: StringPathCreate a path wrapper. Does not create anything on disk.
pathnoneStringThe raw path string this value wraps (a field).
existsnoneBooleanTrue when a file or directory exists at this path.
is_filenoneBooleanTrue when the path exists and is a regular file.
is_directorynoneBooleanTrue when the path exists and is a directory.
namenoneStringThe last path segment, e.g. "notes.txt".
extensionnoneStringThe filename suffix without the dot ("txt"), or "" when there is none.
name_without_extensionnoneStringThe filename with its final extension removed ("archive.tar.gz" → "archive.tar").
absolutenonePathAn absolute form of this path.
normalizenonePathThis path with redundant . and .. segments removed.
sizenoneIntegerSize in bytes as reported by the host; 0 when the path does not exist.
modified_timenoneIntegerLast-modified time in milliseconds since the Unix epoch; 0 when the path does not exist.
parentnone?PathThe containing path, or nil when the path has no parent segment.
childname: StringPathA path for name inside this one.
create_filenonenilCreate an empty file if none exists. The parent directory must exist.
create_directorynonenilCreate this directory. The parent directory must exist.
create_directoriesnonenilCreate this directory and any missing parents.
deletenonenilDelete a file. Does nothing when the path is missing; raises when it is a directory.
delete_treenonenilDelete a file, or a directory and everything under it.
copy_totarget: PathnilCopy a file or a whole directory tree to target, replacing existing files.
move_totarget: PathnilMove or rename a file or directory tree to target.
read_textnoneStringRead the whole file as UTF-8 text.
write_texttext: StringnilWrite text as UTF-8, replacing any existing content.
append_texttext: StringnilAppend text as UTF-8, creating the file if needed.
listnoneArray[Path]The immediate children of a directory; an empty array otherwise.
to_stringnoneStringThe raw path string.

Example

intern io/Path

let root: Path := create Path.make("tmp")
root.create_directories()

let file: Path := root.child("notes.txt")
file.write_text("hello")
file.append_text(" world")

print(file.read_text())               -- "hello world"
print(file.name())                    -- "notes.txt"
print(file.extension())               -- "txt"
print(file.name_without_extension())  -- "notes"
print(file.size())                    -- 11
print(file.parent())                  -- tmp

file.copy_to(root.child("backup.txt"))
print(root.list().length)             -- 2

root.delete_tree()
print(root.exists())                  -- false

Notes

  • delete() removes files only; use delete_tree() for directories.
  • move_to() is implemented as a copy followed by delete_tree() of the source.
  • copy_to() creates missing parent directories of the target.
  • A leading dot does not start an extension: ".bashrc" has extension "".
  • Filesystem failures (missing parent directory, permission denied, reading a missing file) are raised as runtime errors.
  • Text I/O always uses UTF-8.

io/Directory

Directory is a typed wrapper over Path for directory-oriented code, shipped under lib/io/directory.nex. It delegates every operation to an underlying Path; it does not introduce a separate filesystem model.

Loading

intern io/Directory

Support

TargetSupported
JVM REPL / interpreterYes
Generated JVM codeYes

Construction

let logs: Directory := create Directory.make("var/logs")
let same: Directory := create Directory.from_path(create Path.make("var/logs"))

Methods

MethodArgumentsReturnsDescription
makepath: StringDirectoryCreate a directory wrapper from a path string.
from_pathpath: PathDirectoryWrap an existing Path.
pathnonePathThe underlying Path (a field).
existsnoneBooleanTrue only when the path exists and is a directory.
create_directorynonenilCreate this directory. The parent must exist.
create_treenonenilCreate this directory and any missing parents.
deletenonenilDelegates to Path.delete(), which raises for a directory; use delete_tree().
delete_treenonenilDelete the directory and everything under it.
copy_totarget: DirectorynilCopy the directory tree to target.
move_totarget: DirectorynilMove or rename the directory tree to target.
namenoneStringThe directory name (last path segment).
parentnone?DirectoryThe containing directory, or nil when there is no parent segment.
child_dirname: StringDirectoryA Directory for name inside this one.
child_pathname: StringPathA Path for name inside this one, typically a file.
listnoneArray[Path]All immediate children.
directoriesnoneArray[Directory]Immediate child directories only.
filesnoneArray[Path]Immediate child files only.
absolutenoneDirectoryAn absolute form of this directory.
normalizenoneDirectoryThis directory with redundant . and .. segments removed.
to_stringnoneStringA descriptive string such as "Directory(tmp/logs)".

Example

intern io/Path
intern io/Directory

let root: Directory := create Directory.make("tmp")
let logs: Directory := root.child_dir("logs")
logs.create_tree()

logs.child_path("app.log").write_text("started")
root.child_path("readme.txt").write_text("hi")

print(root.directories().length)   -- 1
print(root.files().length)         -- 1
print(logs.name())                 -- "logs"

let archive: Directory := root.child_dir("archive")
logs.copy_to(archive)
print(archive.exists())            -- true

root.delete_tree()

Notes

  • intern io/Directory also loads io/Path, so Path is available without a separate intern.
  • directories() and files() are not recursive.
  • The Directory methods take and return Directory; use child_path() or path to drop to Path for file operations.

io/Text_File

Text_File is a sequential UTF-8 text stream for line-oriented reading, or for writing and appending, shipped under lib/io/text_file.nex. Use it instead of Path.read_text() / write_text() when a file is too large to hold in one string or is produced incrementally.

Loading

intern io/Text_File

Support

TargetSupported
JVM REPL / interpreterYes
Generated JVM codeYes

Construction

let reader: Text_File := create Text_File.open_read(create Path.make("in.txt"))
let writer: Text_File := create Text_File.open_write(create Path.make("out.txt"))
let log:    Text_File := create Text_File.open_append(create Path.make("app.log"))

A file is opened by its constructor; the mode is fixed for the life of the handle.

Methods

MethodArgumentsReturnsDescription
open_readpath: PathText_FileOpen an existing file for reading. Raises when the file does not exist.
open_writepath: PathText_FileOpen for writing, creating the file or truncating existing content.
open_appendpath: PathText_FileOpen for writing at the end, creating the file if needed and keeping existing content.
pathnonePathThe path this file was opened from (a field).
read_linenone?StringThe next line without its line terminator, or nil at end of file.
writetext: StringnilWrite text exactly as given.
write_linetext: StringnilWrite text followed by a newline (\n).
closenonenilClose the underlying stream.
to_stringnoneStringA descriptive string such as "Text_File(log.txt)".

Example

intern io/Path
intern io/Text_File

let path: Path := create Path.make("log.txt")

let writer: Text_File := create Text_File.open_write(path)
writer.write("alpha")
writer.write_line("!")
writer.write_line("beta")
writer.close()

let appender: Text_File := create Text_File.open_append(path)
appender.write_line("gamma")
appender.close()

let reader: Text_File := create Text_File.open_read(path)
let line: ?String := reader.read_line()
from until line = nil do
  print(line)                -- "alpha!", then "beta", then "gamma"
  line := reader.read_line()
end
reader.close()

Notes

  • Writes are flushed immediately, so content is visible to other readers before close().
  • read_line() recognises \n, \r\n and \r line endings.
  • Reading from a handle opened for writing, or writing to one opened for reading, raises a runtime error.
  • Always close() a handle when finished; closing releases the host file descriptor.

io/Binary_File

Binary_File is the byte-oriented file wrapper, shipped under lib/io/binary_file.nex. It supports random access through an explicit cursor.

Bytes are represented as Array[Byte]; a Byte is an unsigned value in 0..255. String.to_bytes() produces one, and a Byte literal is written with a u8 suffix ([0x89u8, 0x50u8]); use Integer.to_byte() to convert a computed Integer.

Loading

intern io/Binary_File

Support

TargetSupported
JVM REPL / interpreterYes
Generated JVM codeYes

Construction

let reader: Binary_File := create Binary_File.open_read(create Path.make("image.png"))
let writer: Binary_File := create Binary_File.open_write(create Path.make("out.bin"))
let log:    Binary_File := create Binary_File.open_append(create Path.make("events.bin"))

Methods

MethodArgumentsReturnsDescription
open_readpath: PathBinary_FileOpen an existing file for reading, with the cursor at 0. Raises when the file does not exist.
open_writepath: PathBinary_FileOpen for writing, creating the file or truncating it to zero length; cursor at 0.
open_appendpath: PathBinary_FileOpen for writing, creating the file if needed; the cursor starts at the current end of file.
pathnonePathThe path this file was opened from (a field).
readcount: IntegerArray[Byte]Read up to count bytes from the cursor and advance it. Returns fewer bytes near end of file and [] at end of file.
read_allnoneArray[Byte]The entire file contents, independent of the cursor. The cursor is not moved.
positionnoneIntegerThe current cursor offset in bytes.
seekoffset: IntegernilMove the cursor to the absolute byte offset. Raises when offset is negative.
writebytes: Array[Byte]nilWrite bytes at the cursor, overwriting existing bytes and extending the file as needed; advances the cursor.
closenonenilClose the underlying file.
to_stringnoneStringA descriptive string such as "Binary_File(data.bin)".

Example

intern io/Path
intern io/Binary_File

let path: Path := create Path.make("data.bin")

let writer: Binary_File := create Binary_File.open_write(path)
writer.write("ABC".to_bytes())
writer.seek(1)
writer.write("Z".to_bytes())       -- overwrite "B"
writer.close()

let appender: Binary_File := create Binary_File.open_append(path)
print(appender.position())         -- 3
appender.write([0x89u8, 0xFFu8])
appender.close()

let reader: Binary_File := create Binary_File.open_read(path)
print(reader.read(2))              -- [65, 90]
print(reader.position())           -- 2
print(reader.read(100))            -- [67, 137, 255]
print(reader.read(1))              -- []
print(reader.read_all())           -- [65, 90, 67, 137, 255]
reader.close()

Notes

  • seek() past the end of file is allowed; a following write() extends the file, padding the gap with zero bytes.
  • Writing to a handle opened with open_read raises a runtime error.
  • Decode bytes back to text with String.from_bytes(), which raises on invalid UTF-8.