-
-
Notifications
You must be signed in to change notification settings - Fork 2
Tiri IO API
The I/O interface provides helper functions for file management and user interactivity. The majority of the functionality is built-in, but UI extensions and file searching are optional, requiring use of the import keyword to load them first.
It should also be noted that while the io interfaces are largely backwards compatible with their Lua counterparts, a key difference is that filesystem failures will throw exceptions to make it easier to capture errors.
The io interface is designed to provide basic filesystem services only. For more advanced filesystem functionality, the Core module and File class provide extensive features that are cross-platform compatible.
file = io.open(Path, [Mode])
Opens the file at Path, requesting access permissions specified by Mode. If Mode is not set, the file is opened in read-only mode. If an error occurs, an exception is thrown with a descriptive error message.
file = io.open('temp:myfile.txt', 'w')Available options for Mode are as follows:
| Option | Description |
|---|---|
| r | Read only. |
| w | Create new file in read/write mode. |
| a | Append to existing file in read/write mode. Automatically creates file if it does not exist. |
| + | Open existing file in read/write mode. |
io.close([File])
Closes the given file handle. If no File is provided, the default output file is closed. Returns true on success.
file = io.open('temp:myfile.txt', 'r')
io.close(file)data1, data2, ... = io.read([Format, ...])
Reads from the default input file according to the given format strings. If no format is provided, a single line is
read. The default input file is initially stdin but can be changed with io.input().
See file:read() for a full description of format strings.
line = io.read() -- Read one line
num = io.read('*n') -- Read a number
all = io.read('*a') -- Read entire fileio.write(Data, ...)
Writes each argument to the default output file. The default output file is initially stdout but can be changed
with io.output(). Arguments must be strings or numbers.
io.write('Hello, ')
io.write('world!\n')io.flush()
Flushes the default output file, ensuring that any buffered data is written to disk.
file = io.input([Source])
When called with no arguments, returns the current default input file handle. When called with a string, opens the named file in read mode and sets it as the default input. When called with a file handle, sets that handle as the default input.
The default input is initially stdin.
io.input('temp:data.txt') -- Set default input to a file
line = io.read() -- Read a line from that file
original = io.input() -- Retrieve the current default inputfile = io.output([Source])
When called with no arguments, returns the current default output file handle. When called with a string, opens the named file in write mode and sets it as the default output. When called with a file handle, sets that handle as the default output.
The default output is initially stdout.
io.output('temp:results.txt') -- Set default output to a file
io.write('Result: 42\n') -- Write to that fileiterator = io.lines([Source])
Returns an iterator function that reads lines from a file. When called with a filename, opens the file and closes it automatically when iteration completes or the iterator is garbage collected. When called with a file handle, iterates lines without closing the handle. When called with no arguments, iterates lines from the default input.
for line in io.lines('temp:data.txt') do
print(line)
endresult = io.type(Value)
Tests whether Value is a valid file handle. Returns "file" if Value is an open file handle, "closed file" if
it is a closed file handle, or nil if it is not a file handle.
file = io.open('temp:test.txt', 'w')
print(io.type(file)) -- "file"
file:close()
print(io.type(file)) -- "closed file"
print(io.type('hello')) -- nilfile = io.tempFile()
Creates a temporary in-memory buffer file opened for both reading and writing. The buffer is backed by system memory, allowing the OS to use swap space for large files. The file is automatically freed when the handle is garbage collected or explicitly closed.
tmp = io.tempFile()
tmp:write('temporary data')
tmp:seek('set', 0)
print(tmp:read('*a')) -- "temporary data"
tmp:close()content = io.readAll(Path)
Reads the entire contents of the file at Path and returns it as a string. This is a convenience function that
opens the file, reads all data, and closes it in a single operation. Throws an exception if the file cannot be
opened or read.
content = io.readAll('config:settings.tiri')io.writeAll(Path, Content)
Writes Content to the file at Path, creating the file if it does not exist or overwriting it if it does. Throws
an exception if the file cannot be created or written to.
io.writeAll('temp:output.txt', 'Hello, world!\n')bool = io.isFolder(Path)
Returns true if Path ends with a folder separator character (/, \ or :), indicating that the path refers to
a directory rather than a file.
print(io.isFolder('system:users/')) -- true
print(io.isFolder('temp:file.txt')) -- falsedir, file = io.splitPath(Path)
Splits Path into its directory and filename components. The directory portion includes the trailing separator.
Returns nil, nil if Path is nil or empty. Returns nil, Path if no separator is found.
dir, file = io.splitPath('system:users/readme.txt')
-- dir = "system:users/"
-- file = "readme.txt"
dir, file = io.splitPath('readme.txt')
-- dir = nil
-- file = "readme.txt"cleaned = io.sanitisePath(Path)
Removes repeated consecutive path separator characters (/, \, :) from Path. Useful for cleaning up
paths constructed by concatenation.
print(io.sanitisePath('system://users///file.txt')) -- "system:/users/file.txt"File handles returned by io.open() and related functions support the following methods, called with the colon
syntax (e.g. file:read()).
data1, data2, ... = file:read([Format, ...])
Reads from the file according to the given format strings. Multiple formats can be provided and each returns a separate value. If no format is provided, a single line is read.
| Format | Description |
|---|---|
| *l | Read a single line, stripping the newline character. This is the default. |
| *a | Read the entire remaining contents of the file. |
| *n | Read a line and convert it to a number. |
| (number) | Read the specified number of bytes. |
file = io.open('temp:data.txt', 'r')
line = file:read() -- Read one line
file:seek('set', 0)
all = file:read('*a') -- Read entire file
file:close()file = file:write(Data, ...)
Writes each argument to the file. Arguments must be strings or numbers. Returns the file handle to allow chained calls.
file = io.open('temp:output.txt', 'w')
file:write('Line 1\n'):write('Line 2\n')
file:close()file:close()
Closes the file handle and releases the underlying file object. Returns true on success.
file:flush()
Flushes any buffered output data to disk, ensuring all writes are committed. Returns true on success.
position = file:seek([Whence, [Offset]])
Sets the file position for reading and writing. Returns the resulting absolute file position.
| Whence | Description |
|---|---|
| set | Position relative to the beginning of the file. |
| cur | Position relative to the current location. This is the default. |
| end | Position relative to the end of the file. |
Offset defaults to 0.
file = io.open('temp:data.txt', 'r')
file:seek('set', 10) -- Move to byte 10
pos = file:seek('cur') -- Get current position
file:seek('end', 0) -- Move to end of file
file:close()iterator = file:lines()
Returns an iterator function that reads lines from the file. The file handle is not closed when iteration completes,
unlike io.lines() with a filename argument.
file = io.open('temp:data.txt', 'r')
for line in file:lines() do
print(line)
end
file:close()The FileSearch interface simplifies the process of searching for files and folders within the file system. Support is provided for both wildcard filters and content searching.
It can be loaded with the line:
import 'io/filesearch'io.search(Path | {PathA, PathB, ...}, Options)
This example searches for text files in the documents: folder that include the word tennis:
import 'io/filesearch'
io.search('documents:', {
nameFilter = regex.new('\\.txt$'),
contentFilter = 'tennis',
maxDepth = 2, -- Only search 2 levels deep
matchFeedback = function(Path, FileName, File)
print(Path, ' ', FileName)
end
})
Valid options to use when defining the search table are as follows:
| Option | Description |
|---|---|
| nameFilter | Include file/folder names that match this filter string exactly, or provide a compiled regex for pattern matching. |
| contentFilter | Include files that contain this content. |
| caseSensitive | Enforces case-sensitive name comparisons if true. |
| matchFeedback | Call this function each time that a matched file is discovered. Returning ERR_Terminate will stop the search. Synopsis: function(Path, File, Attributes)
|
| ignoreFeedback | Call this function each time that a file fails to pass filter matches. |
| minSize | Filter out files that do not meet or exceed this minimum size. |
| maxSize | Filter out files that exceed this size. |
| minDate | Filter out files with a modification time less than this timestamp. |
| maxDate | Filter out files with a modification time exceeding this timestamp. |
| scanLinks | Allows symbolically linked files and folders to be included in the file search. |
| matchFolders | Include matching folder names in the output of the search. |
| ignoreFiles | Do not scan files (useful only in conjunction with matchFolders). |
| maxDepth | Maximum depth to recurse into subdirectories (0 = current directory only, 1 = one level deep, etc.). |
When searching files for content, it is strongly recommended that a filter or size limit is applied so that only a limited number of files are opened for searching.
The File Manager API supports common file management needs such as mass file transfer and clipboard operations, and adds integrated UI support so that user interactions are managed in a consistent way across all Kōtuku applications.
For example, copying a large number of files will pop-up a progress dialog to keep the user informed of progress. If an operation will overwrite an existing file, the user will be notified and given a choice of whether or not to continue.
It can be loaded with the line:
import 'io/filemgr'error = io.ui.copy(Source, Dest, Move)
Copy the Source path or paths (if provided as a list of strings) to the file or folder indicated by Dest.
If Move is true then each file or folder copied from Source will be deleted when the copy is successful.
Any errors that occur will be brought to the user's attention with a dialog box. Exceptions will only be thrown if there a catastrophic failure during the copy process. Otherwise, assume that the resulting error was handled and should only be used as an indicator of the final result. If the user cancels the operation then ERR_Cancelled is returned.
io.ui.paste(Dest)
Paste files from the clipboard to the destination path. The same behavioural rules for io.ui.copy apply.
io.ui.delete(Paths)
Delete the identified file or folder at Paths, which may be a string or list of strings. A progress window is opened if the operation takes longer than expected to run.