Opens the file name and returns it with true, or a closed file and false when that fails.
#import "File";
Opening, reading, writing and managing files and directories by path.
A File is a handle from file_open; read_entire_file and write_entire_file do a whole file in one call, and
map_entire_file_start borrows the content. Names are UTF-8 paths, with / as separator on every target (Windows
accepts \ as well). Every procedure reports failure by its result and does not stop the program. Memory a procedure
returns comes from context.allocator and the caller frees it. Walking directories, copying and metadata are in
File_Utilities.
#import "Extensions/Environment";
base := environment_variable("TMPDIR");
if base == "" base = environment_variable("TEMP");
if base == "" base = "/tmp";
path := tprint("%/jai-doc-file-module.txt", base);
defer file_delete(path);
assert(write_entire_file(path, "hello\n"));
text, ok := read_entire_file(path);
assert(ok && text == "hello\n");
free(text);Procedures#
Native Windows#
Closes file and sets it to the closed state. A file that is already closed, or was never opened, is left alone, so closing
twice is safe. A failure to close is logged and leaves the handle as it was.
Whether file is open: false for a zero File, for one file_open failed to open, and for one file_close closed.
Reads up to bytes_to_read bytes from the current position into vdata, and returns (success, total_read).
The position of the next read or write, in bytes from the start of the file, and whether it could be read.
A closed file gives (0, false).
Moves to byte pos counted from the start of the file. Returns false for a closed file or a negative pos.
Moves by pos bytes relative to .START, .CURRENT or .END of the file. A negative pos goes backwards. Returns
false for a closed file or when the result would be before the start. Going past the end is allowed.
The size of the file in bytes and whether it could be read. The position does not change.
Asks the system to write the file's buffers to the device (FlushFileBuffers); returns false for a closed file or on an error.
Renames the file name_old to name_new, which may be on another volume. Returns false if that fails, including
when name_new already exists: delete it first, or see
File_Utilities.atomic_file_replace_or_just_rename_if_destination_file_does_not_exist.
Deletes the file filename; false if it does not exist, is a directory (see delete_directory) or is read-only. Files this
module opened can be deleted while open.
Creates the hard link link to the existing file filepath, so both names are one file. Note the order: the new name
comes first. Fails if link exists, on a directory, or across volumes or on a file system without hard links.
Removes the directory dirname if it is empty. Returns false if it is missing, not empty, or not a directory.
To remove a folder with its content, see File_Utilities.delete_directory_tree.
Makes sure the directory name exists and returns whether it does afterwards: an existing directory is a success, a file
of that name or (without recursive) a missing parent is a failure. With recursive, missing parents are created too.
Both / and \ work as separators.
The absolute form of relative_path, in a new string from context.allocator that the caller frees, and whether it worked.
Maps the whole file name for reading and returns ok; an empty file succeeds with empty data. Give the result to
munmap_file. A failure is logged through context.logger when log_errors is true, and nothing needs releasing then.
Releases a File_Map_Info: unmaps the view, closes the mapping and the file. Safe to call again on the same record;
returns false if the system refuses.
The path of the machine-wide application data folder (ProgramData), created if missing, in a new UTF-8 string the caller frees; "" on failure.
The path of the current user's Saved Games folder, created if missing, in a new UTF-8 string the caller frees; "" on failure.
The final path of an open file, with links followed, in a new string that the caller frees; "" when file is closed or
the system cannot say. Windows spells it with the \\?\ prefix and \ separators.
File#
The current position of file as (success, position).
Writes all of data to file. Returns false when the file is not open or the write fails or stops short.
Reads the rest of an open file, from its current position to its end, into a new string.
#import "Extensions/Environment";
base := environment_variable("TMPDIR");
if base == "" base = environment_variable("TEMP");
if base == "" base = "/tmp";
path := tprint("%/jai-doc-read-rest.bin", base);
defer file_delete(path);
assert(write_entire_file(path, "abcdef"));
file, ok := file_open(path);
assert(ok);
defer file_close(*file);
assert(file_set_position(file, 2));
rest, read_ok := read_entire_file(file, zero_terminated = true);
assert(read_ok && rest == "cdef" && rest.data[rest.count] == 0);
free(rest);↗Replaces the file name with data: it is created if missing and cut to nothing otherwise. Returns false when it cannot be
opened, written or flushed.
#import "Extensions/Environment";
base := environment_variable("TMPDIR");
if base == "" base = environment_variable("TEMP");
if base == "" base = "/tmp";
path := tprint("%/jai-doc-write-entire.txt", base);
defer file_delete(path);
assert(write_entire_file(path, "a long first version"));
assert(write_entire_file(path, "short"));
text, ok := read_entire_file(path);
assert(ok && text == "short");
free(text);
assert(!write_entire_file(tprint("%/jai-doc-no-such-dir/file", base), "x"));↗Wraps text you already own as a Map_File_Info, so it can go through code that expects one.
Gives a file's whole content as Map_File_Info.data; returns ok as false and empty data when the file cannot be read.
#import "Extensions/Environment";
base := environment_variable("TMPDIR");
if base == "" base = environment_variable("TEMP");
if base == "" base = "/tmp";
path := tprint("%/jai-doc-map-file.txt", base);
defer file_delete(path);
assert(write_entire_file(path, "mapped text"));
info, ok := map_entire_file_start(path);
assert(ok && info.data == "mapped text");
map_entire_file_end(*info);
assert(info.data.count == 0);↗Releases what map_entire_file_start returned and leaves data empty: it unmaps the view on Windows and frees the
text elsewhere. Do not use the old data afterwards. A failure to unmap is logged and data keeps its value.
Types#
An open file. It holds the operating system's HANDLE and nothing else, so a copy of a File is the same open file, not
a second one. Get one from file_open, and give it back with file_close exactly once.
A whole file's bytes, as map_entire_file_start returns them: data is the content, and the record must go back to map_entire_file_end.
A read-only view of a whole file, from map_file: data is its content, mapping the mapping object and file the open file.
Give it back to munmap_file. Writing to data faults.
Constants#
Whether map_entire_file_start maps the file into memory (Windows) or reads it into allocated memory (every other target).
A switch kept for programs that mention it; it is always false and nothing in the module reads it.
The largest s64, kept for programs that compare against it. No procedure of this module returns it. Unix targets only.
The legacy folder id of the roaming application data folder, for Windows APIs that take one. Windows only.
The known-folder flag that creates the folder when it is missing, as get_path_os_program_data and get_path_os_saved_games ask for. Windows only.
The text form of the known-folder id of the Saved Games folder. Windows only.