Implements functionality to read Comma Separated Values and its variants from an input range of dchar
.
Comma Separated Values provide a simple means to transfer and store tabular data. It has been common for programs to use their own variant of the CSV format. This parser will loosely follow the RFC-4180. CSV input should adhere to the following criteria (differences from RFC-4180 in parentheses):
import std.algorithm; import std.array; import std.csv; import std.stdio; import std.typecons; void main() { auto text = "Joe,Carpenter,300000\nFred,Blacksmith,400000\r\n"; foreach (record; csvReader!(Tuple!(string, string, int))(text)) { writefln("%s works as a %s and earns $%d per year", record[0], record[1], record[2]); } // To read the same string from the file "filename.csv": auto file = File("filename.csv", "r"); foreach (record; file.byLine.joiner("\n").csvReader!(Tuple!(string, string, int))) { writefln("%s works as a %s and earns $%d per year", record[0], record[1], record[2]); } } }When an input contains a header the
Contents
can be specified as an associative array. Passing null
to signify that a header is present. auto text = "Name,Occupation,Salary\r" "Joe,Carpenter,300000\nFred,Blacksmith,400000\r\n"; foreach (record; csvReader!(string[string]) (text, null)) { writefln("%s works as a %s and earns $%s per year.", record["Name"], record["Occupation"], record["Salary"]); }This module allows content to be iterated by record stored in a struct, class, associative array, or as a range of fields. Upon detection of an error an CSVException is thrown (can be disabled). csvNextToken has been made public to allow for attempted recovery. Disabling exceptions will lift many restrictions specified above. A quote can appear in a field if the field was not quoted. If in a quoted field any quote by itself, not at the end of a field, will end processing for that field. The field is ended when there is no input, even if the quote was not closed.
Exception containing the row and column for when an exception was thrown.
Numbering of both row and col start at one and corresponds to the location in the file rather than any specified header. Special consideration should be made when there is failure to match the header see HeaderMismatchException
for details.
When performing type conversions, std.conv.ConvException
is stored in the next
field.
Exception thrown when a Token is identified to not be completed: a quote is found in an unquoted field, data continues after a closing quote, or the quoted field was not closed before data was empty.
Data pulled from input before finding a problem
This field is populated when using csvReader
but not by csvNextToken
as this data will have already been fed to the output range.
Exception thrown under different conditions based on the type of Contents
.
Structure, Class, and Associative Array
Determines the behavior for when an error is detected.
Disabling exception will follow these rules:
No exceptions are thrown due to incorrect CSV.
Use exceptions when input has incorrect CSV.
Returns an input
range for iterating over records found in input
.
The Contents
of the input
can be provided if all the records are the same type such as all integer data:
string str = `76,26,22`; int[] ans = [76,26,22]; auto records = csvReader!int(str); foreach (record; records) { assert(equal(record, ans)); }
delimiter
: string str = "Hello;65;63.63\nWorld;123;3673.562"; struct Layout { string name; int value; double other; } auto records = csvReader!Layout(str,';'); foreach (record; records) { writeln(record.name); writeln(record.value); writeln(record.other); }
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 str = "A \" is now part of the data"; auto records = csvReader!(string,Malformed.ignore)(str); auto record = records.front; assert(record.front == str);
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
. 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
.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.
Read only column "b":
string str = "a,b,c\nHello,65,63.63\nWorld,123,3673.562"; auto records = csvReader!int(str, ["b"]); auto ans = [[65],[123]]; foreach (record; records) { assert(equal(record, ans.front)); ans.popFront(); }
header
of different order: string str = "a,b,c\nHello,65,63.63\nWorld,123,3673.562"; struct Layout { int value; double other; string name; } auto records = csvReader!Layout(str, ["b","c","a"]);
header
can also be left empty if the input
contains a header
but all columns should be iterated. The header
from the input
can always be accessed from the header
field. string str = "a,b,c\nHello,65,63.63\nWorld,123,3673.562"; auto records = csvReader(str, null); assert(records.header == ["a","b","c"]);
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
. The returned range provides a header
field for accessing the header
from the input
in array form. string str = "a,b,c\nHello,65,63.63"; auto records = csvReader(str, ["a"]); assert(records.header == ["a","b","c"]);
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
.Lower level control over parsing CSV
This function consumes the input
. After each call the input
will start with either a delimiter or record break (\n, \r\n, \r) which must be removed for subsequent calls.
Range input
| Any CSV input
|
Output ans
| The first field in the input
|
Separator sep
| The character to represent a comma in the specification |
Separator quote
| The character to represent a quote in the specification |
bool startQuoted
| Whether the input should be considered to already be in quotes |
IncompleteCellException
When a quote
is found in an unquoted field, data continues after a closing quote
, or the quoted field was not closed before data was empty.import std.array : appender; import std.range.primitives : popFront; string str = "65,63\n123,3673"; auto a = appender!(char[])(); csvNextToken(str,a,',','"'); writeln(a.data); // "65" writeln(str); // ",63\n123,3673" str.popFront(); a.shrinkTo(0); csvNextToken(str,a,',','"'); writeln(a.data); // "63" writeln(str); // "\n123,3673" str.popFront(); a.shrinkTo(0); csvNextToken(str,a,',','"'); writeln(a.data); // "123" writeln(str); // ",3673"
© 1999–2017 The D Language Foundation
Licensed under the Boost License 1.0.
https://dlang.org/phobos/std_csv.html