This module contains functions to manipulate files.
Some of those functions are low-level, allowing the user
to interact with the file or IO devices, like open/2
,
copy/3
and others. This module also provides higher
level functions that work with filenames and have their naming
based on UNIX variants. For example, one can copy a file
via cp/3
and remove files and directories recursively
via rm_rf/1
Encoding
In order to write and read files, one must use the functions
in the IO
module. By default, a file is opened in binary mode
which requires the functions IO.binread/2
and IO.binwrite/2
to interact with the file. A developer may pass :utf8
as an
option when opening the file, then the slower IO.read/2
and
IO.write/2
functions must be used as they are responsible for
doing the proper conversions and data guarantees.
Note that filenames when given as char lists in Elixir are always treated as UTF-8. In particular, we expect that the shell and the operating system are configured to use UTF8 encoding. Binary filenames are considering raw and passed to the OS as is.
API
Most of the functions in this module return :ok
or
{:ok, result}
in case of success, {:error, reason}
otherwise. Those function are also followed by a variant
that ends with !
which returns the result (without the
{:ok, result}
tuple) in case of success or raises an
exception in case it fails. For example:
File.read("hello.txt")
#=> {:ok, "World"}
File.read("invalid.txt")
#=> {:error, :enoent}
File.read!("hello.txt")
#=> "World"
File.read!("invalid.txt")
#=> raises File.Error
In general, a developer should use the former in case he wants to react if the file does not exist. The latter should be used when the developer expects his software to fail in case the file cannot be read (i.e. it is literally an exception).
Processes and raw files
Every time a file is opened, Elixir spawns a new process. Writing to a file is equivalent to sending messages to that process that writes to the file descriptor.
This means files can be passed between nodes and message passing guarantees they can write to the same file in a network.
However, you may not always want to pay the price for this abstraction.
In such cases, a file can be opened in :raw
mode. The options :read_ahead
and :delayed_write
are also useful when operating large files or
working with files in tight loops.
Check http://www.erlang.org/doc/man/file.html#open-2 for more information about such options and other performance considerations.