Funktionen für die Arbeit mit Dateien stellt das Modul File bereit.
Um eine ganze Datei zu lesen, verwende File.read/1. Um in eine Datei zu schreiben, verwende File.write/2.
Das Modul bietet außerdem Dateifunktionen zum Kopieren, Löschen, Umbenennen usw. Ihre Namen ähneln ihren UNIX-Entsprechungen, zum Beispiel:
File.cp/3 – kopiert eine Datei.File.rm/1 – löscht eine Datei.File.rename/2 – benennt eine Datei um und/oder verschiebt sie.File.mkdir/1 – erstellt ein Verzeichnis.File.cwd/0 – liefert das aktuelle Arbeitsverzeichnis.Alle genannten Funktionen aus dem Modul File haben außerdem eine !-Variante, die einen Fehler auslöst, statt ein Fehler-Tupel zurückzugeben (z. B. File.read!/1). Verwende diese Variante, wenn du nicht vorhast, Fehler wie fehlende Dateien oder fehlende Berechtigungen zu behandeln.
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
Jedes Mal, wenn mit File.write/2 in eine Datei geschrieben wird, wird ein Dateideskriptor geöffnet und ein neuer Elixir-Prozess erzeugt. Aus diesem Grund solltest du es vermeiden, mit File.write/2 in einer Schleife in eine Datei zu schreiben.
Stattdessen kannst du eine Datei mit File.open/2 öffnen. Das zweite Argument von File.open/2 ist eine Liste von Modi, mit der du festlegen kannst, ob du die Datei zum Lesen oder zum Schreiben öffnen möchtest.
Häufig verwendete Modi sind:
:read – zum Lesen öffnen, die Datei muss existieren:write – zum Schreiben öffnen, die Datei wird erstellt, falls sie nicht existiert, vorhandener Inhalt wird überschrieben:append – zum Schreiben öffnen, die Datei wird erstellt, falls sie nicht existiert, vorhandener Inhalt bleibt erhaltenEine vollständige Liste aller Modi findest du in der Dokumentation von File.open/2.
File.open/2 gibt die PID eines Prozesses zurück, der die Datei verwaltet. Um in die Datei zu lesen und zu schreiben, verwende Funktionen aus dem Modul IO und übergib diese PID als IO-Gerät.
Wenn du mit der Arbeit an der Datei fertig bist, schließe sie mit File.close/1.
file = File.open!("README.txt", [:write])
# => #PID<0.157.0>
IO.puts(file, "# README")
# => :ok
File.close(file)
# => :ok
Wenn du eine Datei mit File.read/1 liest, wird die ganze Datei auf einmal in den Speicher geladen. Bei sehr großen Dateien kann das zum Problem werden. Um sie effizient zu verarbeiten, kannst du mit File.open/2 und IO.read/2 die Datei Zeile für Zeile lesen, oder du streamst die Datei mit File.stream/3. Der Stream implementiert sowohl das Enumerable- als auch das Collectable-Protokoll, das heißt, er kann sowohl zum Lesen als auch zum Schreiben verwendet werden.
File.stream!("file.txt")
|> Stream.map(&(&1 <> "!"))
|> Stream.into(File.stream!("new_file.txt"))
|> Stream.run()
Alle Funktionen, die mit Dateien arbeiten, benötigen einen Dateipfad. Dateipfade können absolut oder relativ zum aktuellen Verzeichnis sein. Um Pfade zu bearbeiten, verwende Funktionen aus dem Modul Path. Für plattformübergreifende Kompatibilität erstelle Pfade mit Path.join/1. Es wählt das für die Plattform passende Trennzeichen.
Path.expand(Path.join(["~", "documents", "important.txt"]))
"/home/user/documents/important.txt"