Las funciones para trabajar con ficheros las proporciona el módulo File.
Para leer un fichero entero, usa File.read/1. Para escribir en un fichero, usa File.write/2.
El módulo también proporciona funciones para copiar, eliminar, renombrar, etc. Sus nombres son similares a sus equivalentes en UNIX, por ejemplo:
File.cp/3 - copiar un fichero.File.rm/1 - eliminar un fichero.File.rename/2 - renombrar o mover un fichero.File.mkdir/1 - crear un directorio.File.cwd/0 - obtener el directorio de trabajo actual.Todas las funciones mencionadas del módulo File también tienen una variante con ! que lanza un error en lugar de devolver una tupla de error (por ejemplo, File.read!/1). Usa esa variante si no tienes previsto gestionar errores como ficheros que no existen o falta de permisos.
File.read("does_not_exist")
# => {:error, :enoent}
File.read!("does_not_exist")
# => ** (File.Error) could not read file "does_not_exist": no such file or directory
# (elixir 1.10.4) lib/file.ex:353: File.read!/1
Cada vez que se escribe en un fichero con File.write/2, se abre un descriptor de fichero y se crea un nuevo proceso de Elixir. Por este motivo, conviene evitar escribir en un fichero dentro de un bucle con File.write/2.
En su lugar, puedes abrir un fichero con File.open/2. El segundo argumento de File.open/2 es un array de modos, que te permite indicar si quieres abrir el fichero para lectura o para escritura.
Los modos más usados son:
:read - abrir para lectura, el fichero debe existir:write - abrir para escritura, el fichero se creará si no existe, el contenido existente se sobrescribirá:append - abrir para escritura, el fichero se creará si no existe, el contenido existente se conservaráPara ver todos los modos en detalle, consulta la documentación de File.open/2.
File.open/2 devuelve un PID de un proceso que gestiona el fichero. Para leer y escribir en el fichero, usa funciones del módulo IO y pasa este PID como dispositivo de E/S.
Cuando termines de trabajar con el fichero, ciérralo con File.close/1.
file = File.open!("README.txt", [:write])
# => #PID<0.157.0>
IO.puts(file, "# README")
# => :ok
File.close(file)
# => :ok
Leer un fichero con File.read/1 carga todo el fichero en memoria de una sola vez. Esto puede ser un problema cuando trabajas con ficheros realmente grandes. Para gestionarlos de forma eficiente, puedes usar File.open/2 e IO.read/2 para leer el fichero línea a línea, o puedes hacer streaming del fichero con File.stream/3. El stream implementa los protocolos Enumerable y Collectable, lo que significa que se puede usar tanto para leer como para escribir.
File.stream!("file.txt")
|> Stream.map(&(&1 <> "!"))
|> Stream.into(File.stream!("new_file.txt"))
|> Stream.run()
Todas las funciones que trabajan con ficheros requieren una ruta de fichero. Las rutas de fichero pueden ser absolutas o relativas al directorio actual. Para manipular rutas, usa las funciones del módulo Path. Para ser compatible entre plataformas, usa Path.join/1 para crear rutas. Elegirá el separador adecuado para la plataforma.
Path.expand(Path.join(["~", "documents", "important.txt"]))
"/home/user/documents/important.txt"