csvReader

Returns an input range for iterating over records found in input.

An optional header can be provided. The first record will be read in as the header. If Contents is a struct then the header provided is expected to correspond to the fields in the struct. When Contents is not a type which can contain the entire record, the header must be provided in the same order as the input or an exception is thrown.

  1. auto csvReader(Range input, Separator delimiter, Separator quote)
    csvReader
    (
    Contents = string
    Range
    Separator = char
    )
    (
    Range input
    ,
    Separator delimiter = ','
    ,
    Separator quote = '"'
    )
    if (
    isInputRange!Range &&
    is(immutable ElementType!Range == immutable dchar)
    &&
    isSomeChar!(Separator)
    &&
    !is(Contents T : T[U],
    U : string
    )
    )
  2. auto csvReader(Range input, Header header, Separator delimiter, Separator quote)
  3. auto csvReader(Range input, Header header, Separator delimiter, Separator quote)

Return Value

Type: auto

An input range R as defined by std.range.primitives.isInputRange. When Contents is a struct, class, or an associative array, the element type of R is Contents, otherwise the element type of R is itself a range with element type Contents.

If a header argument is provided, the returned range provides a header field for accessing the header from the input in array form.

Throws

CSVException When a quote is found in an unquoted field, data continues after a closing quote, the quoted field was not closed before data was empty, a conversion failed, or when the row's length does not match the previous length.

HeaderMismatchException when a header is provided but a matching column is not found or the order did not match that found in the input. Read the exception documentation for specific details of when the exception is thrown for different types of Contents.

Examples

The Contents of the input can be provided if all the records are the same type such as all integer data:

import std.algorithm.comparison : equal;
string text = "76,26,22";
auto records = text.csvReader!int;
assert(records.equal!equal([
    [76, 26, 22],
]));

Using a struct with modified delimiter:

import std.algorithm.comparison : equal;
string text = "Hello;65;2.5\nWorld;123;7.5";
struct Layout
{
    string name;
    int value;
    double other;
}

auto records = text.csvReader!Layout(';');
assert(records.equal([
    Layout("Hello", 65, 2.5),
    Layout("World", 123, 7.5),
]));

Specifying ErrorLevel as Malformed.ignore will lift restrictions on the format. This example shows that an exception is not thrown when finding a quote in a field not quoted.

string text = "A \" is now part of the data";
auto records = text.csvReader!(string, Malformed.ignore);
auto record = records.front;

assert(record.front == text);

Read only column "b"

import std.algorithm.comparison : equal;
string text = "a,b,c\nHello,65,63.63\nWorld,123,3673.562";
auto records = text.csvReader!int(["b"]);

assert(records.equal!equal([
    [65],
    [123],
]));

Read while rearranging the columns by specifying a header with a different order"

import std.algorithm.comparison : equal;
string text = "a,b,c\nHello,65,2.5\nWorld,123,7.5";
struct Layout
{
    int value;
    double other;
    string name;
}

auto records = text.csvReader!Layout(["b","c","a"]);
assert(records.equal([
    Layout(65, 2.5, "Hello"),
    Layout(123, 7.5, "World")
]));

The header can also be left empty if the input contains a header row and all columns should be iterated. The header from the input can always be accessed from the header field.

string text = "a,b,c\nHello,65,63.63";
auto records = text.csvReader(null);

assert(records.header == ["a","b","c"]);

Meta

Suggestion Box / Bug Report