Thomas Browne
Thomas Browne

Reputation: 24888

How do I stream into a file in Elixir?

How do I take a stream and write each line to a file?

Say I have a file of words which I stream in using File.stream!, I do some transform on them (here I'm replacing vowels with underscores), but then I want to write this out to a new file. How do I do that? Best I've got so far is this:

iex(3)> ["hello", "my", "friend"] |> Stream.map(&String.replace(&1, ~r{[aeiou]}, "_")) |> Enum.to_list
["h_ll_", "my", "fr__nd"]

Upvotes: 10

Views: 7228

Answers (1)

Dogbert
Dogbert

Reputation: 222188

You need to use File.stream! to open a file in streaming mode, and Stream.into and Stream.run to write the data to that file:

iex(1)> file = File.stream!("a.txt")
%File.Stream{line_or_bytes: :line, modes: [:raw, :read_ahead, :binary], path: "a.txt", raw: true}
iex(2)> ["hello", "my", "friend"] |> Stream.map(&String.replace(&1, ~r{[aeiou]}, "_")) |> Stream.into(file) |> Stream.run
:ok
iex(3)> File.read!("a.txt")
"h_ll_myfr__nd"

Edit: As @FredtheMagicWonderDog pointed out, it's better to just do |> Enum.into(file) instead of |> Stream.into(file) |> Stream.run.

iex(1)> file = File.stream!("a.txt")
%File.Stream{line_or_bytes: :line, modes: [:raw, :read_ahead, :binary], path: "a.txt", raw: true}
iex(2)> ["hello", "my", "friend"] |> Stream.map(&String.replace(&1, ~r{[aeiou]}, "_")) |> Enum.into(file)
%File.Stream{line_or_bytes: :line, modes: [:raw, :read_ahead, :binary], path: "a.txt", raw: true}
iex(3)> File.read!("a.txt")
"h_ll_myfr__nd"

Upvotes: 18

Related Questions