Function std.csv.csvReader
Returns an input range
for iterating over records found in input
.
auto csvReader(Contents, Malformed ErrorLevel = Malformed .throwException, Range, Separator)
(
Range input,
Separator delimiter = ',',
Separator quote = '"',
bool allowInconsistentDelimiterCount = false
)
if (isInputRange!Range && is(immutable(ElementType!Range) == immutable(dchar)) && isSomeChar!Separator && !is(Contents T : T[U], U : string));
auto csvReader(Contents, Malformed ErrorLevel = Malformed .throwException, Range, Header, Separator)
(
Range input,
Header header,
Separator delimiter = ',',
Separator quote = '"',
bool allowInconsistentDelimiterCount = false
)
if (isInputRange!Range && is(immutable(ElementType!Range) == immutable(dchar)) && isSomeChar!Separator && isForwardRange!Header && isSomeString!(ElementType!Header));
auto csvReader(Contents, Malformed ErrorLevel = Malformed .throwException, Range, Header, Separator)
(
Range input,
Header header,
Separator delimiter = ',',
Separator quote = '"',
bool allowInconsistentDelimiterCount = false
)
if (isInputRange!Range && is(immutable(ElementType!Range) == immutable(dchar)) && isSomeChar!Separator && is(Header : typeof(null)));
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.
Returns
An input range R as defined by
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
.
Example
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],
]));
Example
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),
]));
Example
Specifying ErrorLevel
as Malformed
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;
writeln(record .front); // text
Example
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],
]));
Example
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")
]));
Example
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);
writeln(records .header); // ["a", "b", "c"]
Example
Handcrafted csv files tend to have an variable amount of columns.
By default std
will throw if the number of columns on a line
is unequal to the number of columns of the first line.
To allow, or disallow, a variable amount of columns a bool
can be passed to
all overloads of the csvReader
function as shown below.
import std .algorithm .comparison : equal;
string text = "76,26,22\n1,2\n3,4,5,6";
auto records = text .csvReader!int(',', '"', true);
assert(records .equal!equal([
[76, 26, 22],
[1, 2],
[3, 4, 5, 6]
]));
Example
ditto
import std .algorithm .comparison : equal;
static struct Three
{
int a;
int b;
int c;
}
string text = "76,26,22\n1,2\n3,4,5,6";
auto records = text .csvReader!Three(',', '"', true);
assert(records .equal([
Three(76, 26, 22),
Three(1, 2, 0),
Three(3, 4, 5)
]));
Example
ditto
import std .algorithm .comparison : equal;
auto text = "Name,Occupation,Salary\r" ~
"Joe,Carpenter,300000\nFred,Blacksmith\r\n";
auto r = csvReader!(string[string])(text, null, ',', '"', true);
assert(r .equal([
[ "Name" : "Joe", "Occupation" : "Carpenter", "Salary" : "300000" ],
[ "Name" : "Fred", "Occupation" : "Blacksmith" ]
]));
Authors
Jesse Phillips