英語版
このページの英語版を見る

std.csv

カンマ区切り値とその変種を読み取る機能を実装する。 をdchar入力範囲から読み取る機能を実装している。
カンマ区切り値は、表形式データを転送・保存する簡単な手段を提供する。 表データを転送・保存する簡単な手段を提供する。プログラムが独自の を使うのが一般的である。このパーサーは RFC-4180に従っている。CSV入力は以下の基準に従うべきである。 RFC-4180との違いは括弧内に示す):
  • レコードは改行(CRLF,LF,CR)で区切られる。
  • 最後のレコードは改行で終わってもよい
  • ヘッダーは入力の最初のレコードとして提供することができる。
  • レコードがカンマで区切られたフィールドを持つ(カスタマイズ可能)
  • 改行、カンマ、二重引用符を含むフィールドは、二重引用符で囲む(カスタマイズ可能)。 二重引用符で囲む(カスタマイズ可能)。
  • フィールド内の二重引用符は二重引用符でエスケープされる
  • 各レコードは同じ数のフィールドを含むべきである

例:

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]);
    }

    // ファイル"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]);
    }
}
}
入力がヘッダーを含む場合、Contents は連想配列として指定できる。 連想配列として指定できる。NULLを渡すと、ヘッダーが存在することを示す。
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"]);
}

// ファイル"filename.csv"から同じ文字列を読み込む:

auto file = File("filename.csv", "r");

foreach (record; csvReader!(string[string])
        (file.byLine.joiner("\n"), null))
{
    writefln("%s works as a %s and earns $%s per year.",
             record["Name"], record["Occupation"],
             record["Salary"]);
}
このモジュールは、構造体や連想配列、フィールドの範囲として格納されたレコードによってコンテンツを反復処理することができる、 クラス、連想配列、またはフィールドの範囲として格納されたレコードによってコンテンツを反復処理することができる。エラーを検出すると エラーが検出されると CSVException がスローされる(無効にすることもできる)。 は,回復を試みるために public にされている。
例外を無効にすると、上記の多くの制限が解除される。引用符 がフィールドに現れることがある。引用符で囲まれたフィールドに 引用符で囲まれたフィールドの場合、フィールドの最後でなく、引用符単体で囲まれると、そのフィールドの処理は終了する。 フィールドの処理を終了する。引用符が閉じられていなくても、入力がなくなるとフィールドは終了する。 閉じられる。

Authors:
Jesse Phillips

ソース std/csv.d

class CSVException: object.Exception;
例外が発生した際の行と列を含む。
行番号も列番号も1から始まり、指定されたヘッダーではなくファイル内の位置に対応する。 に対応する。指定されたヘッダーではなく、ファイル内の位置に対応する。 ヘッダーにマッチしない場合は、特別な配慮が必要である。 HeaderMismatchExceptionを参照のこと。
型変換を行う場合、 std.conv.ConvExceptionに格納される。 next フィールドに格納される。
Examples:
import std.exception : collectException;
import std.algorithm.searching : count;
string text = "a,b,c\nHello,65";
auto ex = collectException!CSVException(csvReader(text).count);
// "(Row: 0, Col: 0) Row 2's length 2 does not match previous length of 3."("(行: 0, 列: 0) 2行目の長さ2が以前の長さ3と一致しない。")
writeln(ex.toString);
Examples:
import std.exception : collectException;
import std.algorithm.searching : count;
import std.typecons : Tuple;
string text = "a,b\nHello,65";
auto ex = collectException!CSVException(csvReader!(Tuple!(string,int))(text).count);
// "(Row: 1, Col: 2) Unexpected 'b' when converting from type string to type int"("(行: 1, 列: 2) 文字列型からint型への変換時に予期せぬ 'b'が発生した。")
writeln(ex.toString);
size_t row;
size_t col;
class IncompleteCellException: std.csv.CSVException;
トークンが完了していないことが確認されたときにスローされる例外。 引用符で囲まれていないフィールドで引用符が見つかった、引用符を閉じた後もデータが続いている、あるいはデータが空になる前に引用符で囲まれたフィールドが閉じられていない。 引用符で囲まれていないフィールドに引用符が見つかった、引用符を閉じた後もデータが続いている、またはデータが空になる前に引用符で囲んだフィールドが閉じられていない。
Examples:
import std.exception : assertThrown;
string text = "a,\"b,c\nHello,65,2.5";
assertThrown!IncompleteCellException(text.csvReader(["a","b","c"]));
dstring partialData;
問題が見つかる前に入力からデータが引き出された
このフィールドは csvReader には入力されるが csvNextTokenこのデータは このデータはすでに出力レンジに供給されているからである。
class HeaderMismatchException: std.csv.CSVException;
Contents"型"に基づいて異なる条件でスローされる例外。
構造体、クラス、連想配列
  • ヘッダーが提供されたが、マッチするカラムが見つからない場合
その他
  • ヘッダーが提供されたが、一致するカラムが見つからない場合
  • オーダーが入力されたものと一致しない
ヘッダで指定されたカラムがデータ中に見つからない場合、行と列は意味をなさない。 ヘッダで指定された列がデータ中に見つからない場合、行と列は意味を持たないので、rowとcolの両方が0になる。そうでなければ rowは常に1であり、colはheaderで最初に見つかったインスタンスである。 1より前に発生したものである。
Examples:
import std.exception : assertThrown;
string text = "a,b,c\nHello,65,2.5";
assertThrown!HeaderMismatchException(text.csvReader(["b","c","invalid"]));
enum Malformed: int;
エラーが検出されたときの動作を決定する。
例外の無効化はこれらのルールに従う:
  • フィールドが引用符で囲まれていない場合、フィールドに引用符が現れることがある。
  • フィールドが引用符で囲まれていない場合、フィールド内に引用符が現れることがある。 フィールドの最後でなく、引用符単体であった場合、そのフィールドの処理は終了する。
  • 引用符が閉じられていなくても、入力がなくなるとフィールドは終了する。 が閉じられていなくても、入力がなくなるとフィールドは終了する。
  • 与えられたヘッダーが入力の順序と一致しない場合 の内容は入力で見つかったとおりに返される。
  • 与えられたヘッダが入力にないカラムを含む場合、それらは無視される。 は無視される。
Examples:
import std.algorithm.comparison : equal;
import std.algorithm.searching : count;
import std.exception : assertThrown;

string text = "a,b,c\nHello,65,\"2.5";
assertThrown!IncompleteCellException(text.csvReader.count);

// 例外を無視して、無効なCSVを処理してみる
auto firstLine = text.csvReader!(string, Malformed.ignore)(null).front;
assert(firstLine.equal(["Hello", "65", "2.5"]));
ignore
CSVが正しくないために例外がスローされることはない。
throwException
入力のCSVが正しくない場合に例外を使用する。
auto csvReader(Contents = string, Malformed ErrorLevel = Malformed.throwException, Range, Separator = char)(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 = string, Malformed ErrorLevel = Malformed.throwException, Range, Header, Separator = char)(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 = string, Malformed ErrorLevel = Malformed.throwException, Range, Header, Separator = char)(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)));
入力範囲を返す で見つかったレコードを反復処理するために input.
オプションの headerを指定できる。最初のレコードは がヘッダーとして読み込まれる。Contents が構造体である場合、提供されるヘッダーは構造体のフィールドに対応することが期待される。 構造体のフィールドに対応することが期待される。Contents 。 がレコード全体を格納できる型でない場合、ヘッダは構造体のフィールドに対応する。 headerは を入力と同じ順序で提供しなければならない。
Returns:
次式で定義される入力範囲R std.range.primitives.isInputRange.Contents 。 が構造体、クラス、または連想配列である場合、Rの要素型は Contents であり、そうでない場合はRの要素型自体が Contents である。
引数 header引数が与えられる、 を提供する。 headerフィールドを提供する。 に配列形式でアクセスするためのフィールドを提供する。
Throws:
CSVException引用符で囲まれていないフィールドに引用符が見つかった場合、 引用符で囲まれていないフィールドに引用符が見つかった場合、引用符を閉じた後もデータが続いている データが空になる前に閉じられなかった場合、変換に失敗した場合、行の長さが前の長さと一致しない場合などである。 行の長さが前の長さと一致しない場合などである。
HeaderMismatchException ヘッダが提供されたが 一致するカラムが見つからないか、入力で見つかった順序と一致しない場合 と一致しない。の詳細については、例外のドキュメントを参照のこと。 Contents 、例外がスローされる。
Examples:
すべてのレコードが同じ型である場合、入力のContents 。 入力の、すべてのレコードが整数データなど同じ型である場合に提供できる:
import std.algorithm.comparison : equal;
string text = "76,26,22";
auto records = text.csvReader!int;
assert(records.equal!equal([
    [76, 26, 22],
]));
Examples:
区切り文字を変更した構造体を使用する:
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),
]));
Examples:
としてErrorLevel を指定する。 Malformed.ignoreを指定すると の制限を解除する。この例は、引用符で囲まれていないフィールドに引用符を見つけたときに例外がスローされないことを示している。 例外が発生しないことを示している。
string text = "A \" is now part of the data";
auto records = text.csvReader!(string, Malformed.ignore);
auto record = records.front;

writeln(record.front); // text
Examples:
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],
]));
Examples:
異なる順序のヘッダーを指定して列を並べ替えながら読む"
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")
]));
Examples:
入力にヘッダー行が含まれている場合、ヘッダーは空のままにしておくこともできる。 があり、すべてのカラムが反復処理される必要がある場合は、ヘッダーを空のままにすることもできる。 入力からのヘッダーは常に headerフィールドからアクセスできる。
string text = "a,b,c\nHello,65,63.63";
auto records = text.csvReader(null);

writeln(records.header); // ["a", "b", "c"]
Examples:
手作りのcsvファイルは、カラムの数が可変である傾向がある。
デフォルトでは、std.csv 、行の列数が最初の行の列数と等しくない場合にスローされる。 をスローする。 可変カラム数を許可または不許可にするには、bool 。 のすべてのオーバーロードに渡すことができる。 csvReader関数のすべてのオーバーロードに渡すことができる。
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]
]));
Examples:
同上
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)
]));
Examples:
同上
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" ]
]));
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(immutable(ElementType!Range) == immutable(dchar)) && isOutputRange!(Output, dchar));
CSVを解析する下位レベルの制御
この関数は入力を消費する。この関数は入力を消費する。 入力は区切り文字かレコード区切り(⊖n、⊖r、⊖r)で始まる。 で始まる。
Parameters:
Range input 任意のCSV入力
Output ans 入力の最初のフィールド
Separator sep カンマを表す文字
Separator quote 引用符を表す文字
bool startQuoted 入力がすでに 引用符
Throws:
IncompleteCellException引用符で囲まれていないフィールドに引用符がある場合 引用符で囲まれていないフィールドに引用符が見つかった場合、データは引用符を閉じた後も続く。 が閉じられていない。
Examples:
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"