README.md

# CSVLixir

A CSV reader/writer for Elixir. Operates on files or strings.

## Reading

### Files

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.

    iex> CSVLixir.read("path/to/my.csv") \
    ...>   |> Enum.to_list
    [["row", "one"], ["row", "two"]]
    
### Strings

Parsing CSV data from a string returns a list of lists. Use
`CSVLixir.parse`.

    iex> CSVLixir.parse("abc,def,ghi\n123,456,789")
    [["abc","def","ghi"],["123","456","789"]]

    iex> CSVLixir.parse(~s{abc,def,"gh"",""i"})
    [["abc", "def", "gh\",\"i"]]

    iex> CSVLixir.parse(File.read!("/tmp/foo.csv"))
    [["row", "one"], ["row", "two"]]

## Writing

`CSVLixir.write` transforms a possibly lazy list of lists into a stream of
CSV strings. Each generated string ends with a newline.

    iex> CSVLixir.write([["first", "row"], [123, 456]]) \
    ...>   |> Enum.to_list
    ["first,row\n", "123,456\n"]

    iex> 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.

    iex> CSVLixir.write_row(["a", "b", "c"])
    "a,b,c\n"

### Writing to a file

Writing using streams:

    iex> f = File.open!("/tmp/csvlixir.csv", [:write])
    iex> 1..3 \
    ...>   |> Stream.map(&([&1, &1+1 ,&1+2])) \
    ...>   |> CSVLixir.write \
    ...>   |> Stream.each(&(IO.write(f, &1))) \
    ...>   |> Stream.run
    iex> File.close(f)
    iex> File.read!("/tmp/csvlixir.csv")
    "1,2,3\n2,3,4\n3,4,5\n"

Writing a line at a time:

    iex> f = File.open!("/tmp/csvlixir.csv", [:write, :utf8])
    iex> IO.write(f, CSVLixir.write_row(["garçon", "waiter"]))
    iex> IO.write(f, CSVLixir.write_row(["résumé", "resume"]))
    iex> File.close(f)
    iex> 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.)

# Changes from 1.0

Adds reading from/writing to files. Removes support for char lists.

# To Do

- Allow different separator characters besides comma.
- Handle headers. Return map instead of list, perhaps?