As funções para trabalhar com arquivos são fornecidas pelo módulo File.
Para ler um arquivo inteiro, use File.read/1. Para escrever em um arquivo, use File.write/2.
O módulo também fornece funções de arquivo para copiar, remover, renomear etc. Seus nomes são semelhantes aos equivalentes no UNIX, por exemplo:
File.cp/3 - copiar um arquivo.File.rm/1 - excluir um arquivo.File.rename/2 - renomear e/ou mover um arquivo.File.mkdir/1 - criar um diretório.File.cwd/0 - obter o diretório de trabalho atual.Todas as funções mencionadas do módulo File também têm uma variante com ! que gera um erro em vez de retornar uma tupla de erro (por exemplo, File.read!/1). Use essa variante se você não pretende tratar erros como arquivos inexistentes ou falta de permissões.
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
Toda vez que um arquivo é escrito com File.write/2, um descritor de arquivo é aberto e um novo processo do Elixir é criado. Por esse motivo, deve-se evitar escrever em um arquivo dentro de um laço usando File.write/2.
Em vez disso, um arquivo pode ser aberto usando File.open/2. O segundo argumento de File.open/2 é uma lista de modos, que permite especificar se você quer abrir o arquivo para leitura ou para escrita.
Os modos usados com mais frequência são:
:read - abre para leitura, o arquivo precisa existir:write - abre para escrita, o arquivo será criado se não existir, o conteúdo existente será sobrescrito:append - abre para escrita, o arquivo será criado se não existir, o conteúdo existente será preservadoPara uma lista completa de todos os modos, consulte a documentação de File.open/2.
File.open/2 retorna um PID de um processo que lida com o arquivo. Para ler e escrever no arquivo, use funções do módulo IO e passe esse PID como o dispositivo IO.
Quando terminar de trabalhar com o arquivo, feche-o com File.close/1.
file = File.open!("README.txt", [:write])
# => #PID<0.157.0>
IO.puts(file, "# README")
# => :ok
File.close(file)
# => :ok
Ler um arquivo com File.read/1 carrega o arquivo inteiro na memória de uma só vez. Isso pode ser um problema ao trabalhar com arquivos realmente grandes. Para lidar com eles de forma eficiente, você pode usar File.open/2 e IO.read/2 para ler o arquivo linha por linha, ou pode transmitir o arquivo com File.stream/3. O stream implementa tanto o protocolo Enumerable quanto o Collectable, o que significa que pode ser usado tanto para leitura quanto para escrita.
File.stream!("file.txt")
|> Stream.map(&(&1 <> "!"))
|> Stream.into(File.stream!("new_file.txt"))
|> Stream.run()
Todas as funções que trabalham com arquivos exigem um caminho de arquivo. Os caminhos de arquivo podem ser absolutos ou relativos ao diretório atual. Para manipular caminhos, use funções do módulo Path. Para compatibilidade entre plataformas, use Path.join/1 para criar caminhos. Ele escolherá o separador adequado à plataforma.
Path.expand(Path.join(["~", "documents", "important.txt"]))
"/home/user/documents/important.txt"