d3-dsv
此模块为delimiter-separated values(分隔符分隔值)提供了一个parser和formatter,通常为comma-separated values(逗号分隔值(CSV))或tab-separated values(制表符分隔值(TSV))。这些表格格式很受电子表格程序(如微软的Excel)的欢迎,而且通常比JSON更节约空间。此实现基于RFC 4180。
逗号(CSV)和制表符(TSV)分隔符是内置的。例如,解析:
d3.csvParse("foo,bar\n1,2"); // [{foo: "1", bar: "2"}, columns: ["foo", "bar"]]
d3.tsvParse("foo\tbar\n1\t2"); // [{foo: "1", bar: "2"}, columns: ["foo", "bar"]]
或者格式化:
d3.csvFormat([{foo: "1", bar: "2"}]); // "foo,bar\n1,2"
d3.tsvFormat([{foo: "1", bar: "2"}]); // "foo\tbar\n1\t2"
想要使用不同的分隔符,如对pipe-separated values使用“|”,可以使用d3.dsvFormat:
var psv = d3.dsvFormat("|");
console.log(psv.parse("foo|bar\n1|2")); // [{foo: "1", bar: "2"}, columns: ["foo", "bar"]]
想在浏览器中更方便的加载DSV文件,另请参阅d3-fetch的d3.scv和d3.tsv方法。
Installing
如果你使用npm,请键入npm install d3-dsv
。否则,请下载最新版本。你也可以直接从d3js.org加载,作为standalone library(独立库)或D3 4.0的一部分来使用。支持AMD,CommonJS和vanilla环境。在vanilla环境下,会输出一个全局的d3
:
<script src="https://d3js.org/d3-dsv.v1.min.js"></script>
<script>
var data = d3.csvParse(string);
</script>
API Reference
d3.csvParse(string[, row])
d3.csvParseRows(string[, row])
d3.csvFormat(rows[, columns])
d3.csvFormatRows(rows)
相当于dsvFormat(",").formatRows。
d3.tsvParse(string[, row])
d3.tsvParseRows(string[, row])
d3.tsvFormat(rows[, columns])
d3.tsvFormatRows(rows)
相当于dsvFormat("\t").formatRows。
d3.dsvFormat(delimiter)
为给定delimiter构建一个新的DSV parser和formatter。delimiter必须是一个字符(即,一个16位代码单元);因此ASCII分隔符可以,而emoji分隔符就不行。
dsv.parse(string[, row])
解析给定的string,该string必须是分隔符分隔值格式,且有恰当的分隔符,返回代表已解析行的对象数组。
与dsv.parseRows不同的是,这种方法需要的DSV内容的第一行包含一个分隔符分隔的列名列表;这些列名会成为返回对象的属性。例如,下面的CSV文件:
Year,Make,Model,Length
1997,Ford,E350,2.34
2000,Mercury,Cougar,2.38
生成的JavaScript数组为:
[
{"Year": "1997", "Make": "Ford", "Model": "E350", "Length": "2.34"},
{"Year": "2000", "Make": "Mercury", "Model": "Cougar", "Length": "2.38"}
]
返回的数组也暴露出了包含按输入顺序排列的列名的colums
属性(与Object.keys相反,其迭代顺序是任意的)。例如:
data.columns; // ["Year", "Make", "Model", "Length"]
如果不指定row转换函数,则字段值为字符串。为了安全,不会自动转换到数字、日期或其他类型。在某些情况下,JavaScript会自动将字符串强制转换为数字(例如,使用+
运算符),但更好的是制定row转换函数。
如果指定了row转换函数,则为每行调用给定的函数,并传入一个对象,表示当前行(d),第一个非标题行从0开始的索引(i)和列名数组。如果返回值为null或undefined,则会跳过该行,并在由dsv.parse返回的数组中省略;否则,返回值定义了相应的行对象。例如:
var data = d3.csvParse(string, function(d) {
return {
year: new Date(+d.Year, 0, 1), // lowercase and convert "Year" to Date
make: d.Make, // lowercase
model: d.Model, // lowercase
length: +d.Length // lowercase and convert "Length" to number
};
});
注意:使用+
比parseInt或parseFloat更快,但更严格。例如,对“30px”
使用+
进行转换时返回NaN,而parseInt和parseFloat返回30
。
dsv.parseRows(string[, row])
解析给定的string,该string必须是分隔符分隔值格式,且有恰当的分隔符,返回代表已解析行的对象数组。
与dsv.parse不同的是,此方法将标题行视为标准行,不管DSV内容是否包含标题。每一行都表示为数组而不是对象。行的长度可能不一致。例如,由如下CSV文件,它明显缺少标题行:
1997,Ford,E350,2.34
2000,Mercury,Cougar,2.38
生成的JavaScript数组为:
[
["1997", "Ford", "E350", "2.34"],
["2000", "Mercury", "Cougar", "2.38"]
]
如果不指定row转换函数,则字段值为字符串。为了安全,不会自动转换到数字、日期或其他类型。在某些情况下,JavaScript会自动将字符串强制转换为数字(例如,使用+运算符),但更好的是制定row转换函数。
如果指定了row转换函数,则为每行调用给定的函数,并传入一个对象,表示当前行(d),第一个非标题行从0开始的索引(i
)和列名数组。如果返回值为null或undefined,则会跳过该行,并在由dsv.parse返回的数组中省略;否则,返回值定义了相应的行对象。例如:
var data = d3.csvParseRows(string, function(d, i) {
return {
year: new Date(+d[0], 0, 1), // convert first colum column to Date
make: d[1],
model: d[2],
length: +d[3] // convert fourth column to number
};
});
实际上,row类似于对返回行应用了一个map和filter运算符。
dsv.format(rows[, columns])
将给定的rows对象数组格式化为分隔符分隔值,并返回一个字符串。这是dsv.parse的逆操作。每一行由换行符(\n
)进行分隔,行中的每一列由分隔符(如逗号,
)进行分隔。包含分隔符、双引号("
)或换行符的值都将使用双引号进行编码。
如果不指定columns,则标题行的列名将由rows中所有对象的所有属性一起决定;列的顺序是不确定的。如果指定了columns,则它是表示列名的字符串数组。例如:
var string = d3.csvFormat(data, ["year", "make", "model", "length"]);
每个行对象上的所有字段都将被强制为字符串。如何控制和格式化呢,首先将rows映射至一个由字符串数组组成的数组中,然后使用dsv.formatRows。
dsv.formatRows(rows)
将给定的由字符串rows数组组成的数组格式化为分隔符分隔值,并返回一个字符串。这是dsv.parseRows的逆操作。每一行由换行符(\n
)进行分隔,行中的每一列由分隔符(如逗号,
)进行分隔。包含分隔符、双引号("
)或换行符的值都将使用双引号进行编码。
想要将一个对象数组转换为指定列的多维数组,可以使用array.map。例如:
var string = d3.csvFormatRows(data.map(function(d, i) {
return [
d.year.getFullYear(), // Assuming d.year is a Date object.
d.make,
d.model,
d.length
];
}));
如果你喜欢,也可以使用array.concat将这个结果与列名结合起来生成第一行:
var string = d3.csvFormatRows([[
"year",
"make",
"model",
"length"
]].concat(data.map(function(d, i) {
return [
d.year.getFullYear(), // Assuming d.year is a Date object.
d.make,
d.model,
d.length
];
})));
Content Security Policy
如果使用了content security policy(网页安全策略),由于对快速解析使用了(安全的)动态代码生成,dsv.parse需要script-src
指令中有unsafe-eval
。(另请参阅source)另外,使用 dsv.parseRows时也是。
Byte-Order Marks
DSV文件有时会以byte order mark (BOM)开始;例如,在微软的Excel中使用CSV UTF-8格式保存一个电子表格时就会包含一个BOM。在网上这通常不是一个问题,因为在编码标准中指定了UTF-8 decode algorithm以去除BOM。另一方面,Node.js在解码UTF-8时不会去除BOM。
如果不去除BOM,文本的第一个字符将是一个宽度为0的non-breaking space(不间断空格)。所以,如果用d3.csvParse解析一个带有BOM的CSV文件,第一列的名称将以一个宽度为0的non-breaking space(不间断空格)开头。这很难发现,因为这个字符通常在打印时是看不见的。
想要在解析前去除BOM,可以考虑使用strip-bom。
Command Line Reference
dsv2dsv
dsv2dsv [options…] [file]
将给定的DSV输入file转换为DSV(通常有一个不同的分隔符或编码)。如果不指定file,则默认从stdin读取。例如,将CSV转换为TSV:
csv2tsv < example.csv > example.tsv
将windows-1252 CSV转换为utf-8 CSV:
dsv2dsv --input-encoding windows-1252 < latin1.csv > utf8.csv
dsv2dsv -h
dsv2dsv --help
输出使用信息。
dsv2dsv -V
dsv2dsv --version
输出版本号。
dsv2dsv -o file
dsv2dsv --out file
指定输出文件名。默认值为“-”表示stdout。
dsv2dsv -r delimiter
dsv2dsv --input-delimiter delimiter
指定输入分隔符。默认为“,”用于读取CSV。(你可以通过在命令行键入⌃V以输入一个换行符)
dsv2dsv --input-encoding encoding
指定输入字符编码。默认为“utf8”。
dsv2dsv -w _delimiter
_ {#dsv2dsv--w-delimiter-}
dsv2dsv --output-delimiter delimiter
指定输出分隔符。默认为“,”用于读取CSV。(你可以通过在命令行键入⌃V以输入一个换行符)
dsv2dsv --output-encoding encoding
指定输出字符编码。默认为“utf8”。
csv2tsv [options…] [file]
tsv2csv [options…] [file]
dsv2json
dsv2json [options…] [file]
将给定的DSV输入file转换为JSON。如果不指定file,则默认从stdin读取。例如,将CSV转换为JSON:
csv2json < example.csv > example.json
或者将CSV转换为以制表符分隔的JSON流:
csv2json -n < example.csv > example.ndjson
dsv2json -h
dsv2json --help
输出使用信息。
dsv2json -V
dsv2json --version
输出版本号。
dsv2json -o file
dsv2json --out file
指定输出文件名。默认值为“-”表示stdout。
dsv2json -r delimiter
dsv2json --input-delimiter delimiter
指定输入分隔符。默认为“,”用于读取CSV。(你可以通过在命令行键入⌃V以输入一个换行符)
dsv2json --input-encoding encoding
指定输入字符编码。默认为“utf8”。
dsv2json -r encoding
dsv2json --output-encoding encoding
指定输出字符编码。默认为“utf8”。
dsv2json -n
dsv2json --newline-delimited
输出以换行符为分隔符的JSON,而不是一个JSON数组。
csv2json [options…] [file]
相当于dsv2json。
tsv2json [options…] [file]
json2dsv
json2dsv [options…] [file]
将给定的JSON输入file转换为DSV。如果不指定file,则默认从stdin读取。例如,将JSON转换为CSV:
json2csv < example.json > example.csv
或者将以制表符分隔的JSON流转换为CSV:
json2csv -n < example.ndjson > example.csv
json2dsv -h
json2dsv --help
输出使用信息。
json2dsv -V
json2dsv --version
输出版本号。
json2dsv -o file
json2dsv --out file
指定输出文件名。默认值为“-”表示stdout。
json2dsv --input-encoding encoding
指定输入字符编码。默认为“utf8”。
json2dsv -w delimiter
json2dsv --output-delimiter delimiter
指定输出分隔符。默认为“,”用于写入CSV。(你可以通过在命令行键入⌃V以输入一个换行符)
json2dsv --output-encoding encoding
指定输出字符编码。默认为“utf8”。
json2dsv -n
json2dsv --newline-delimited
输出以换行符为分隔符的JSON,而不是一个JSON数组。
json2csv [options…] [file]
相当于json2dsv。