erl_csv (erl_csv v0.6.0)

View Source

A simple library for encoding and decoding RFC 4180 compliant CSV.

It can encode Erlang terms into CSV iolist/0 and decode CSV binaries back into rows of binaries, either all at once or lazily from a file stream.

All input and output is treated as UTF-8: multi-byte codepoints are preserved verbatim on both the encoding and the decoding path.

Summary

Functions

Decode a chunk of comma-separated lines into rows.

Open a file and return a lazy csv_stream/0 to be consumed with decode_s/1.

Decode the next rows out of a csv_stream/0 returned by decode_new_s/1,2.

Encode a table into a stream of RFC 4180 compliant CSV lines for writing to a file or other IO.

Types

csv_stream()

-type csv_stream() ::
          #csv_stream{hd :: iodata(), tl :: erl_csv:csv_stream_fun(), opts :: erl_csv:decode_opts()} |
          stream_end.

csv_stream_fun()

-type csv_stream_fun() :: fun(() -> maybe_csv_stream()).

decode_opts()

-type decode_opts() :: #{quotes => <<_:8>>, separator => <<_:8>>, delimiter => binary()}.

Options accepted by decode/2 and decode_new_s/2.

encode_opts()

-type encode_opts() :: #{headers => boolean() | list(), separator => <<_:8>>, delimiter => binary()}.

Options accepted by encode/2.

maybe_csv_stream()

-type maybe_csv_stream() :: csv_stream() | {error, term()}.

Functions

decode(Input)

-spec decode(iodata()) ->
                {ok, iodata()} |
                {has_trailer, iodata(), iodata()} |
                {nomatch, iodata()} |
                {error, term()}.

Equivalent to decode(Input, #{}).

decode(Input, Opts)

-spec decode(iodata(), decode_opts()) ->
                {ok, iodata()} |
                {has_trailer, iodata(), iodata()} |
                {nomatch, iodata()} |
                {error, term()}.

Decode a chunk of comma-separated lines into rows.

The decoder expects line by line input of valid CSV lines with inlined escape sequences if you use it directly. When the chunk ends in the middle of a line, {has_trailer, Decoded, Trailer} is returned so the caller can prepend Trailer to the next chunk.

Options

  • separator — The separator token to use, defaults to <<",">>. Must be a single byte.
  • delimiter — The line delimiter token to use, defaults to <<"\\n">>. May be more than one byte, e.g. <<"\\r\\n">>.
  • quotes — The quoting token to use, defaults to <<"\\"">>. Must be a single byte.

decode_new_s(Input)

-spec decode_new_s(file:name_all()) -> {ok, csv_stream()} | {error, term()}.

Equivalent to decode_new_s(Input, #{}).

decode_new_s(Input, Opts)

-spec decode_new_s(file:name_all(), decode_opts()) -> {ok, csv_stream()} | {error, term()}.

Open a file and return a lazy csv_stream/0 to be consumed with decode_s/1.

Accepts the same options as decode/2.

decode_s(Input)

-spec decode_s(csv_stream()) -> {ok, iolist(), csv_stream()} | {error, term()}.

Decode the next rows out of a csv_stream/0 returned by decode_new_s/1,2.

Returns the decoded rows together with the continuation stream. When the stream is exhausted, the returned rows are [] and the stream is stream_end.

If the input ends inside a quoted field that is never closed, the call returns {error, {unterminated_quoted_field, Trailer}}, where Trailer is the raw text of that row.

encode(Input)

-spec encode(iolist() | [map()]) -> iolist().

Equivalent to encode(Input, #{}).

encode(Input, Opts)

-spec encode(iolist() | [map()], encode_opts()) -> iolist().

Encode a table into a stream of RFC 4180 compliant CSV lines for writing to a file or other IO.

Options

  • separator — The separator token to use, defaults to <<",">>. Must be a single byte.
  • delimiter — The line delimiter token to use, defaults to <<"\\n">>.
  • headers — When set to true, uses the keys of the first map as the first element in the stream. All subsequent elements are the values of the maps, looked up under those keys. When set to a list, uses the given list as the first element in the stream and orders all subsequent elements using that list. When set to false (the default), uses the raw inputs as elements. When set to anything but false, all elements in the input are assumed to be maps, and every map must hold every header key.

Cells

Binaries and strings are written as they are, and quoted when they contain the separator, the delimiter, a line break or a quote. Integers are written in decimal, and floats in the shortest form that reads back as the same float. Atoms are written as io_lib:write_atom/1 does, and any other term in Erlang syntax, always quoted. All text is written as UTF-8.