Files and IO

Additional functionality to handle files and directories. Note that while these functions are contained within different namespaces it is perfectly fine to use them together.

Files and Directories

These are functions contained in the files namespace provided by SuperBLT.

Listing all directories in a folder

file.GetDirectories(path)

Get all child directories of the specified path, relative to the PAYDAY 2 executable.
path The path to check for child directories.

Listing all files in a folder

file.GetFiles(path)

Get all files inside the specified directory dir.
dir The directory to check for any child files.

Deleting an empty directory

file.RemoveDirectory(path)

Removes an empty directory at directory path.
path The path to the directory to remove.
returns True if the directory was removed, false if the directory could not be removed.

Checking if a directory exists

file.DirectoryExists(path)

Checks if directory at path exists or not.
path The path to the directory to check if it exists.
returns True if the directory exists, false is the directory does not.

Example:

local path = "mods/my_mod/"
if file.DirectoryExists(path) then
  file.RemoveDirectory(path)
end

IO

These are functions contained within the io namespace.

Checking if a file can be read

io.file_is_readable(fname)

Checks if a file can be opened to read from.
fname The path and file name to check.
returns True if the file can be opened for reading, false otherwise.

Example:

local path = "mods/saves/save_data.json"
if io.file_is_readable(path) then
  local data = io.load_as_json(path)
end

Deleting a directory containing files

io.remove_directory_and_files(path, verbose)

Recursively deletes all files and folders from the directory specified.
path The directory to attempt to remove all child files and folders.
verbose Wether to print verbose output to the log, optional.
returns True if the operation was successful, false if the remove failed at any point during the remove.

Saving data as JSON

io.save_as_json(data, path)

Converts a Lua table to a JSON string and saves it to a file.
data The data to save as JSON file.
path The path and file name to save the data to.
returns True if the operation was successful, false otherwise.

Example:

local my_data = {
  value1 = true,
  value2 = 1,
  value3 = "hello world"
}
io.save_as_json(my_data, "mods/saves/save_data.json")

This will create a JSON file at the specified path with the following content:

{"value1":true,"value2":1,"value3":"hello world"}

Note that JSON only supports simple types, to save game specific types like Vector3 or Color you need to convert them first. The Networking Extensions provide a few type conversion functions.

Loading data from JSON

io.load_as_json(path)

Loads a file containing JSON data and converts it into a Lua table.
path The path and file name to load the data from.
returns The table containing the data, or nil if loading wasn't successful.

Example:

local my_data = io.load_as_json("mods/saves/save_data.json")
if my_data then
  log(my_data.value1)
end

Asynchronous IO

The async IO API lets Lua read and write large files without locking up the game. This can be particularly useful for reading or writing lots of small files, where the delay from the OS opening each one can be very significant.

Note: When a callback is run, it's only ever called between two frames. Thus if you try loading a thousand files one at a time (each time one callback completes, starting the next read) then it will take at least a thousand frames, even if the actual IO operations are much faster than that.

Note: On Windows, automatic newline conversion is disabled so it's safe to read and write binary data. This is the same as supplying b as an option to io.open.

Note: The error messages returned may vary between Windows and Linux.

Reading a file asynchronously

blt.async_io.read(path, function(data, err))

Reads the contents of a file, then calls the given callback function when the read is complete.

If the read completed successfully, the callback is invoked with a single argument, that being the string representation of the file contents.

If an error occurred, the callback is invoked with two arguments: first nil and then a string with the error message.

Example:

blt.async_io.read("mods/testing/test.lua", function(data, err)
  log("Read data async (valid): " .. tostring(data) .. ":" .. tostring(err))
end)

blt.async_io.read("mods/testing/this file does not exist", function(data, err)
  log("Read data async (invalid): " .. tostring(data) .. ":" .. tostring(err))
end)

Will print (not necessarily in this order):

Read data async (valid): <contents of the file goes here>:nil
Read data async (invalid): nil:No such file or directory

Writing a file asynchronously

blt.async_io.write(path, data, function(status, err))

Asynchronously writes the given data to a file. If the file already exists, it is overwritten.

If the call was successful, the callback runs with a single argument: true.

If the call failed, the callback runs with false as the first argument and the error message from the OS as the second one.

Example:

blt.async_io.write("mods/testing/my-test-output-file.txt", "Hello, World", function(status, err)
  if not status then
    log("Failed to write file " .. path .. " : " .. tostring(err))
  end
end)