The task is to save and load a HashDict of structs to and from a file, using Elixir. I was planning on iterating over the HashDict and writing out a struct on each line of the file. However, I was unable to find anything on Google on how to save a Struct or Dict to a file. In particular, is there a built-in way of serialising Dicts?
I tried converting to a string first. The iex snippet:-
iex(68)> {:ok,of} = File.open("ztest.txt", [:write, :utf8])
{:ok, #PID<0.232.0>}
iex(69)> IO.write(of, {:atuple, "abc"})
** (Protocol.UndefinedError) protocol String.Chars not implemented for {:atuple, "abc"}
One wonders how to make an implementation of String.chars for a map or a tuple?
Also, is it possible to pipe the output of IO.inspect into a file? My attempts to do this were unsuccessful.
The hash of a file is useful, for example, to check if the content of two files is identical, or if the content was corrupted during the download. There are different hash functions, MD5, SHA-1, SHA-2, SHA-3 etc. , many of them available in Elixir.
But there is another function that Elixir gives us which can also be used to read files. That function is called File.stream!/1 . This function works by reading a file one line at a time. This is useful in cases where we might be reading very large files.
It takes two arguments: 1) the path we want to write to 2) the contents that we want to put in the file. It works like this: iex> File.write ( "fixed-haiku.txt", fixed_contents) :ok Elixir dutifully takes the file path and the fixed contents and puts them into a file called fixed-haiku.txt. Well, we assume so.
Can you make Elixir write a program for itself? Put this code into a file called script.ex with File.write/2: IO.puts "This file was generated from Elixir" and then make it run by running elixir that-file.ex . Figure out what happens if you try to delete a file that doesn't exist with File.rm/1.
You can use :erlang.term_to_binary
and :erlang.binary_to_term
to serialized and deserialize your HashDict
:
iex> dict = HashDict.new |> Dict.put(:struct1, %{some: :struct})
#HashDict<[struct1: %{some: :struct}]>
iex> File.write! "encoded.txt", :erlang.term_to_binary(dict)
:ok
iex> File.read!("encoded.txt") |> :erlang.binary_to_term
#HashDict<[struct1: %{some: :struct}]>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With