A CSV reader/writer for Elixir. Operates on files or strings.
Add CSVLixir to your mix.exs
dependencies:
def deps do [{:csvlixir, "~> 2.0.3"}] end
Run mix deps.get
. Done.
To read CSV data from a file, use CSVLixir.read
. It takes a path to a file and returns a Stream
that generates and returns rows of CSV data.
CSVLixir.read("path/to/my.csv") |> Enum.to_list #=> [["row", "one"], ["row", "two"]]
Parsing CSV data from a string returns a list of lists. Use CSVLixir.parse
.
CSVLixir.parse("abc,def,ghi\n123,456,789") #=> [["abc","def","ghi"],["123","456","789"]] CSVLixir.parse(~s{abc,def,"gh"",""i"}) #=> [["abc", "def", "gh\",\"i"]] CSVLixir.parse(File.read!("/tmp/foo.csv")) #=> [["row", "one"], ["row", "two"]]
CSVLixir.write
transforms a possibly lazy list of lists into a stream of CSV strings. Each generated string ends with a newline.
CSVLixir.write([["first", "row"], [123, 456]]) |> Enum.to_list #=> ["first,row\n", "123,456\n"] CSVLixir.write([["abc", "def", "gh\",\"i"], [123, 456, 789]]) |> Enum.each(&IO.write/1) #=> abc,def,"gh"",""i" #=> 123,456,789 #=> :ok
CSVLixir.write_row
takes a single list and returns a single string.
CSVLixir.write_row(["a", "b", "c"]) #=> "a,b,c\n"
Writing using streams:
f = File.open!("/tmp/csvlixir.csv", [:write]) 1..3 |> Stream.map(&([&1, &1+1 ,&1+2])) |> CSVLixir.write |> Stream.each(&(IO.write(f, &1))) |> Stream.run File.close(f) File.read!("/tmp/csvlixir.csv") # => "1,2,3\n2,3,4\n3,4,5\n"
Writing a line at a time:
f = File.open!("/tmp/csvlixir.csv", [:write, :utf8]) IO.write(f, CSVLixir.write_row(["garçon", "waiter"])) IO.write(f, CSVLixir.write_row(["résumé", "resume"])) File.close(f) File.read!("/tmp/csvlixir.csv") # => "garçon,waiter\nrésumé,resume\n"
Don't forget to specify :utf8
when opening the file for writing if needed. (I often forget.)
Adds reading from/writing to files. Removes support for char lists.
- Allow different separator characters besides comma.
- Handle headers. Return map instead of list, perhaps?