std.csv

Переметиться к: CSVException · csvNextToken · csvReader · HeaderMismatchException · IncompleteCellException · Malformed

Реализует функциональность для чтения формата Comma Separated Values (значений, разделённых запятыми) и его вариантов из входного диапазона символов dchar.
Формат Comma Separated Values (значения, разделённые запятыми) предоставляет простое средство для переноса и хранения табличных данных. В программах обычно используется собственный вариант CSV-формата. Этот анализатор будет свободно следовать RFC-4180. Входной CSV-файл должен соответствовать следующим критериям (в скобках отличия от RFC-4180):

Example:

import std.algorithm;
import std.array;
import std.csv;
import std.stdio;
import std.typecons;

void main()
{
    auto text = "Джо,плотником,300000\nФред,кузнецом,400000\r\n";

    foreach (record; csvReader!(Tuple!(string, string, int))(text))
    {
        writefln("%s работает %s и зарабатывает $%d в год.",
                 record[0], record[1], record[2]);
    }

    // Чтобы прочитать ту же строку из файла "filename.csv":

    auto file = File("filename.csv", "r");
    foreach (record;
        file.byLine.joiner("\n").csvReader!(Tuple!(string, string, int)))
    {
        writefln("%s работает %s и зарабатывает $%d в год.",
                 record[0], record[1], record[2]);
    }
}
}
Когда вход содержит заголовок, содержимое может быть представлено в виде ассоциативного массива. Передача аргумента null означает, что заголовок присутствует.
auto text = "Name,Occupation,Salary\r"
    "Джо,плотником,300000\nФред,кузнецом,400000\r\n";

foreach (record; csvReader!(string[string])
        (text, null))
{
    writefln("%s работает %s и зарабатывает $%s в год.",
             record["Name"], record["Occupation"],
             record["Salary"]);
}
Этот модуль позволяет итерировать содержимое по записям, сохраняемым в структуре, классе, ассоциативном массиве, или в виде диапазона полей. При обнаружении ошибки генерируется исключение CSVException (можно отключить). csvNextToken сделан публичным, чтобы предоставить возможность сделать попытку восстановления.
Отключение исключений отменяет многие ограничения, указанные выше. Кавычка может появиться внутри поля, если поле не было обрамлено кавычками. Если в обрамлённом кавычками поле присутсвует любая кавычка сама по себе, а не в конце поля, она завершит обработку для этого поля. Поле заканчивается, если нет ничего на входе, даже если кавычка не была закрыта.

Смотрите также:
Wikipedia Comma-separated values
Википедия CSV
Лицензия:
Boost License 1.0.
Авторы:
Jesse Phillips

Исходный код: std/csv.d

Переметиться к: col · row

class CSVException: object.Exception;
Исключение, содержащее строку и столбец, для которых оно было брошено.
Нумерация строк и столбцов начинается с единицы и соответствует местоположению в файле, а не какому-либо указанному заголовку. Особое внимание нужно уделить, если не удаётся сопоставить заголовок, подробнее смотрите в HeaderMismatchException.
При выполнении преобразований типов, исключение std.conv.ConvException хранится в поле next.
size_t row;
size_t col;

Переметиться к: partialData

class IncompleteCellException: std.csv.CSVException;
Исключение, выбрасываемое в случае, когда идентифицируемый токен не завершён: кавычка найдена в поле, необрамлённом кавычками, данные продолжаются после закрывающей кавычки, или поле в кавычках не было закрыто до того, как данные закончились.
dstring partialData;
Данные, извлечённые со входа до появления проблемы
Это поле заполняется при использовании csvReader, но не csvNextToken, так как эти данные уже будут переданы в выходной диапазон.
class HeaderMismatchException: std.csv.CSVException;
Исключение выбрасываемое при разных обстоятельствах в зависимости от типа Contents (содержимого).
Структура, Класс и Ассоциативный массив
  • Когда предоставлен заголовок, но не найден соответствующий столбец
Иное
  • Когда предоставлен заголовок, но не найден соответствующий столбец
  • Порядок не соответствует тому, что обнаружено на входе
Поскольку номера строки и столбец не имеют смысла, если столбец, указанный в заголовке, не найден в данных, то как row, так и row будут равны нулю. В противном случае row всегда равна 1, а col – первому экземпляру, найденному в заголовке, который попался перед предыдущим запуском на одном. Otherwise row is always one and col is the first instance found in header that occurred before the previous starting at one.

Переметиться к: ignore · throwException

enum Malformed: int;
Определяет поведение при обнаружении ошибки.
Отключение исключений будет следовать этим правилам:
  • Кавычка может появиться в поле, если поле не было обрамлено кавычками.
  • Если в обрамлённом кавычками поле появится любая кавычка сама по себе, а не в конце поля, то обработка для этого поля будет завершена.
  • Поле заканчивается, когда закончились входные данные, даже если кавычка не была закрыта.
  • Если заданный заголовок не соответствует порядку во входных данных, содержимое возвращается в том же порядке, как и во входных данных.
  • Если заданный заголовок содержит столбцы, не найденные на входе, они будут игнорироваться.
ignore
Исключения из-за неверного CSV отключены.
throwException
Если на входе неверный CSV, используются исключения.

Переметиться к: 2 · 3

auto csvReader(Contents = string, Malformed ErrorLevel = Malformed.throwException, Range, Separator = char)(Range input, Separator delimiter = ',', Separator quote = '"')
if (isInputRange!Range && is(Unqual!(ElementType!Range) == dchar) && isSomeChar!Separator && !is(Contents T : T[U], U : string));
Возвращает входной диапазон для итерирования по записям, найденным в input.
Для input может быть предоставлен тип содержимого Contents, если все записи одного типа, например, все данные целочисленные:
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 как Malformed.ignore отменяет ограничения на формат. Этот пример показывает, что исключение не возникает при обнаружении кавычки в поле, не обрамлённом кавычками.
string str = "A \" is now part of the data";
auto records = csvReader!(string, Malformed.ignore)(str);
auto record = records.front;

assert(record.front == str);
Возвращает:
Входной диапазон с элементами типа R, как определено в std.range.primitives.isInputRange. Если Contents является структурой, классом или ассоциативным массивом, тип элемента R становится равен Contents, в противном случае тип элемента R сам представляет собой диапазон с элементами типа Contents.
Исключения:
CSVException, если символ quote (кавычка по-умолчанию) найден в поле, необрамлённом этими символами, данные продолжаются после закрывающей кавычки, обрамлённое кавычками поле не было закрыто до того, как данные закончились, не удалось преобразование типа, или если длина строки не соответствует предыдущей длине.
HeaderMismatchException, если предоставлен заголовок, но не найден соответствующий столбец, или если порядок не совпадает с тем, который обнаружен в input. Прочтите документацию об исключениях для получения подробной информации о том, когда вызывается исключение для разных типов содержимого Contents.
auto csvReader(Contents = string, Malformed ErrorLevel = Malformed.throwException, Range, Header, Separator = char)(Range input, Header header, Separator delimiter = ',', Separator quote = '"')
if (isInputRange!Range && is(Unqual!(ElementType!Range) == dchar) && isSomeChar!Separator && isForwardRange!Header && isSomeString!(ElementType!Header));
Может быть предоставлен необязательный заголовок header. Первая запись будет прочитана как заголовок. Если Contents – это структура, то предоставленный заголовок должен соответствовать полям в структуре. Если Contents не является типом, который может содержать в себе всю запись, header должен быть предоставлен в том же порядке, как и на входе, или будет выброшено исключение.
Чтение только колонки "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 отличающегося порядка:
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 также может быть пустым, если input содержит заголовок, но все столбцы нужно обработать. Заголовок, полученный со входа input всегда можно получить через поле header.
string str = "a,b,c\nHello,65,63.63\nWorld,123,3673.562";
auto records = csvReader(str, null);

assert(records.header == ["a","b","c"]);
Возвращает:
Входной диапазон с элементами типа R, как определено в std.range.primitives.isInputRange. Если Contents является структурой, классом или ассоциативным массивом, тип элемента R становится равен Contents, в противном случае тип элемента R сам представляет собой диапазон с элементами типа Contents.
Возвращаемый диапазон предоставляет поле header для доступа к заголовку из входа в форме массива.
string str = "a,b,c\nHello,65,63.63";
auto records = csvReader(str, ["a"]);

assert(records.header == ["a","b","c"]);
Исключения:
CSVException, если символ quote (кавычка по-умолчанию) найден в поле, необрамлённом этими символами, данные продолжаются после закрывающей кавычки, обрамлённое кавычками поле не было закрыто до того, как данные закончились, не удалось преобразование типа, или если длина строки не соответствует предыдущей длине.
HeaderMismatchException, если предоставлен заголовок, но не найден соответствующий столбец, или если порядок не совпадает с тем, который обнаружен в input. Прочтите документацию об исключениях для получения подробной информации о том, когда вызывается исключение для разных типов содержимого Contents.
auto csvReader(Contents = string, Malformed ErrorLevel = Malformed.throwException, Range, Header, Separator = char)(Range input, Header header, Separator delimiter = ',', Separator quote = '"')
if (isInputRange!Range && is(Unqual!(ElementType!Range) == dchar) && isSomeChar!Separator && is(Header : typeof(null)));
void csvNextToken(Range, Malformed ErrorLevel = Malformed.throwException, Separator, Output)(ref Range input, ref Output ans, Separator sep, Separator quote, bool startQuoted = false)
if (isSomeChar!Separator && isInputRange!Range && is(Unqual!(ElementType!Range) == dchar) && isOutputRange!(Output, dchar));
Низкоуровневый контроль над синтаксическим анализом CSV-формата.
Эта функция потребляет данные из входа input. После каждого вызова input начинается с разделителя delimiter или с символов конца записи (\n, \r\n, \r), которые необходимо удалить для последующих вызовов.
Параметры:
Range input Любой CSV-вход
Output ans Первое поле со входа
Separator sep Символ, представляющий запятую в спецификации
Separator quote Символ, представляющий кавычку в спецификации
bool startQuoted Следует ли считать, что входные данные уже должны быть в кавычках Whether the input should be considered to already be in quotes
Исключения:
IncompleteCellException, если кавычка обнаружена в поле, необрамлённом кавычками, данные продолжаются после закрывающей кавычки, или обрамлённое кавычками поле не было закрыто до того, как данные закончились.
Примеры:
import std.array : appender;
string str = "65,63\n123,3673";

auto a = appender!(char[])();

csvNextToken(str,a,',','"');
assert(a.data == "65");
assert(str == ",63\n123,3673");

str.popFront();
a.shrinkTo(0);
csvNextToken(str,a,',','"');
assert(a.data == "63");
assert(str == "\n123,3673");

str.popFront();
a.shrinkTo(0);
csvNextToken(str,a,',','"');
assert(a.data == "123");
assert(str == ",3673");