Skip to content

Commit 6901d21

Browse files
committed
Merge pull request #37 from doug-martin/master
v0.3.0
2 parents e2fc34c + 2a17742 commit 6901d21

File tree

10 files changed

+246
-53
lines changed

10 files changed

+246
-53
lines changed

.jshintrc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
"boss": false,
3434
"debug": false,
3535
"eqnull": true,
36-
"es5": true,
3736
"esnext": true,
3837
"evil": false,
3938
"expr": true,

History.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# v0.3.0
2+
3+
* You can now specify `objectMode` when parsing a csv which will cause `data` events to have an object emitted.
4+
* You can now pipe directly to the stream returned from `createWriteStream`
5+
* You can now transform csvs by piping output from parsing into a formatter.
6+
17
# v0.2.5
28

39
* Fixed issue where not all rows are emitted when using `pause` and `resume`

README.md

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
<a name="top"></a>
2-
3-
4-
[![build status](https://secure.travis-ci.org/C2FO/fast-csv.png)](http://travis-ci.org/C2FO/fast-csv)
1+
[![build status](https://secure.travis-ci.org/C2FO/fast-csv.png)](http://travis-ci.org/C2FO/fast-csv)
52
# Fast-csv
63

74
This is a library that provides CSV parsing and formatting.
@@ -18,6 +15,7 @@ This is a library that provides CSV parsing and formatting.
1815

1916
All methods accept the following `options`
2017

18+
* `objectMode=true`: Ensure that `data` events have an object emitted rather than the stringified version set to false to have a stringified buffer.
2119
* `headers=false`: Ste to true if you expect the first line of your `CSV` to contain headers, alternatly you can specify an array of headers to use.
2220
* `ignoreEmpty=false`: If you wish to ignore empty rows.
2321
* `delimiter=','`: If your data uses an alternate delimiter such as `;` or `\t`.
@@ -33,7 +31,6 @@ All methods accept the following `options`
3331

3432
**events**
3533

36-
`parse-error`: Emitted if there was an error parsing a row.
3734
`record`: Emitted when a record is parsed.
3835
`data-invalid`: Emitted if there was invalid row encounted, **only emitted if the `validate` function is used**.
3936
`data`: Emitted with the `stringified` version of a record.
@@ -56,7 +53,7 @@ var csvStream = csv()
5653
stream.pipe(csvStream);
5754
```
5855

59-
**`.fromPath(path[, options])**
56+
**`.fromPath(path[, options])`**
6057

6158
This method parses a file from the specified path.
6259

@@ -73,7 +70,7 @@ csv
7370
});
7471
```
7572

76-
**`.fromString(string[, options])**
73+
**`.fromString(string[, options])`**
7774

7875
This method parses a string
7976

@@ -94,7 +91,7 @@ csv
9491
});
9592
```
9693

97-
**`.fromStream(stream[, options])**
94+
**`.fromStream(stream[, options])`**
9895

9996
This accepted a readable stream to parse data from.
10097

@@ -223,7 +220,7 @@ This is the lowest level of the write methods, it creates a stream that can be u
223220
224221
```javascript
225222
var csvStream = csv.createWriteStream({headers: true}),
226-
writableStream = fs.createWritableStream("my.csv");
223+
writableStream = fs.createWriteStream("my.csv");
227224

228225
writableStream.on("finish", function(){
229226
console.log("DONE!");
@@ -333,6 +330,37 @@ csv.writeToString([
333330
], {headers: true}); //"a,b\na1,b1\na2,b2\n"
334331
```
335332
333+
## Piping from Parser to Writer
334+
335+
You can use `fast-csv` to pipe the output from a parsed CSV to a transformed CSV by setting the parser to `objectMode` and using `createWriteStream`.
336+
337+
```javascript
338+
csv
339+
.fromPath("in.csv", {headers: true})
340+
.pipe(csv.createWriteStream({headers: true}))
341+
.pipe(fs.createWriteStream("out.csv", {encoding: "utf8"}));
342+
```
343+
344+
When piping from a parser to a formatter the transforms are maintained also.
345+
346+
347+
```javascript
348+
csv
349+
.fromPath("in.csv", {headers: true})
350+
.transform(function(obj){
351+
return {
352+
name: obj.Name,
353+
address: obj.Address,
354+
emailAddress: obj.Email_Address,
355+
verified: obj.Verified
356+
};
357+
})
358+
.pipe(csv.createWriteStream({headers: true}))
359+
.pipe(fs.createWriteStream("out.csv", {encoding: "utf8"}));
360+
```
361+
362+
The output will contain formatted result from the transform function.
363+
336364
## Benchmarks
337365
338366
`Parsing 20000 records AVG over 3 runs`
@@ -371,11 +399,3 @@ MIT <https://github.com/C2FO/fast-csv/raw/master/LICENSE>
371399
* Code: `git clone git://github.com/C2FO/fast-csv.git`
372400
* Website: <http://c2fo.com>
373401
* Twitter: [http://twitter.com/c2fo](http://twitter.com/c2fo) - 877.465.4045
374-
375-
##Namespaces
376-
377-
378-
379-
380-
381-
##Classes

docs/History.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,12 @@
176176

177177

178178

179+
<h1>v0.3.0</h1>
180+
<ul>
181+
<li>You can now specify <code>objectMode</code> when parsing a csv which will cause <code>data</code> events to have an object emitted.</li>
182+
<li>You can now pipe directly to the stream returned from <code>createWriteStream</code></li>
183+
<li>You can now transform csvs by piping output from parsing into a formatter.</li>
184+
</ul>
179185
<h1>v0.2.5</h1>
180186
<ul>
181187
<li>Fixed issue where not all rows are emitted when using <code>pause</code> and <code>resume</code></li>

docs/index.html

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,7 @@
177177

178178

179179

180-
<p><a name="top"></a></p>
181-
<p> <a href="http://travis-ci.org/C2FO/fast-csv"><img src="https://secure.travis-ci.org/C2FO/fast-csv.png" alt="build status"></a></p>
180+
<p><a href="http://travis-ci.org/C2FO/fast-csv"><img src="https://secure.travis-ci.org/C2FO/fast-csv.png" alt="build status"></a></p>
182181
<h1>Fast-csv</h1>
183182
<p>This is a library that provides CSV parsing and formatting.</p>
184183
<p><strong>NOTE</strong> As of v0.2.0 <code>fast-csv</code> supports multi-line values.</p>
@@ -188,6 +187,7 @@ <h2>Usage</h2>
188187
<h3>Parsing</h3>
189188
<p>All methods accept the following <code>options</code></p>
190189
<ul>
190+
<li><code>objectMode=true</code>: Ensure that <code>data</code> events have an object emitted rather than the stringified version set to false to have a stringified buffer.</li>
191191
<li><code>headers=false</code>: Ste to true if you expect the first line of your <code>CSV</code> to contain headers, alternatly you can specify an array of headers to use.</li>
192192
<li><code>ignoreEmpty=false</code>: If you wish to ignore empty rows.</li>
193193
<li><code>delimiter=&#39;,&#39;</code>: If your data uses an alternate delimiter such as <code>;</code> or <code>\t</code>.<ul>
@@ -207,8 +207,7 @@ <h3>Parsing</h3>
207207
</li>
208208
</ul>
209209
<p><strong>events</strong></p>
210-
<p><code>parse-error</code>: Emitted if there was an error parsing a row.
211-
<code>record</code>: Emitted when a record is parsed.
210+
<p><code>record</code>: Emitted when a record is parsed.
212211
<code>data-invalid</code>: Emitted if there was invalid row encounted, <strong>only emitted if the <code>validate</code> function is used</strong>.
213212
<code>data</code>: Emitted with the <code>stringified</code> version of a record.</p>
214213
<p><strong>([options])</strong></p>
@@ -224,7 +223,7 @@ <h3>Parsing</h3>
224223
});
225224

226225
stream.pipe(csvStream);</code></pre>
227-
<p><strong>`.fromPath(path[, options])</strong></p>
226+
<p><strong><code>.fromPath(path[, options])</code></strong></p>
228227
<p>This method parses a file from the specified path.</p>
229228
<pre class='prettyprint linenums lang-js'><code class="lang-javascript">var csv = require(&quot;fast-csv&quot;);
230229

@@ -236,7 +235,7 @@ <h3>Parsing</h3>
236235
.on(&quot;end&quot;, function(){
237236
console.log(&quot;done&quot;);
238237
});</code></pre>
239-
<p><strong>`.fromString(string[, options])</strong></p>
238+
<p><strong><code>.fromString(string[, options])</code></strong></p>
240239
<p>This method parses a string</p>
241240
<pre class='prettyprint linenums lang-js'><code class="lang-javascript">var csv = require(&quot;fast-csv&quot;);
242241

@@ -252,7 +251,7 @@ <h3>Parsing</h3>
252251
.on(&quot;end&quot;, function(){
253252
console.log(&quot;done&quot;);
254253
});</code></pre>
255-
<p><strong>`.fromStream(stream[, options])</strong></p>
254+
<p><strong><code>.fromStream(stream[, options])</code></strong></p>
256255
<p>This accepted a readable stream to parse data from.</p>
257256
<pre class='prettyprint linenums lang-js'><code class="lang-javascript">var stream = fs.createReadStream(&quot;my.csv&quot;);
258257

@@ -342,7 +341,7 @@ <h3>Formatting</h3>
342341
<p><strong><code>createWriteStream(options)</code></strong></p>
343342
<p>This is the lowest level of the write methods, it creates a stream that can be used to create a csv of unknown size and pipe to an output csv.</p>
344343
<pre class='prettyprint linenums lang-js'><code class="lang-javascript">var csvStream = csv.createWriteStream({headers: true}),
345-
writableStream = fs.createWritableStream(&quot;my.csv&quot;);
344+
writableStream = fs.createWriteStream(&quot;my.csv&quot;);
346345

347346
writableStream.on(&quot;finish&quot;, function(){
348347
console.log(&quot;DONE!&quot;);
@@ -417,6 +416,26 @@ <h3>Formatting</h3>
417416
{a: &quot;a1&quot;, b: &quot;b1&quot;},
418417
{a: &quot;a2&quot;, b: &quot;b2&quot;}
419418
], {headers: true}); //&quot;a,b\na1,b1\na2,b2\n&quot;</code></pre>
419+
<h2>Piping from Parser to Writer</h2>
420+
<p>You can use <code>fast-csv</code> to pipe the output from a parsed CSV to a transformed CSV by setting the parser to <code>objectMode</code> and using <code>createWriteStream</code>.</p>
421+
<pre class='prettyprint linenums lang-js'><code class="lang-javascript">csv
422+
.fromPath(&quot;in.csv&quot;, {headers: true})
423+
.pipe(csv.createWriteStream({headers: true}))
424+
.pipe(fs.createWriteStream(&quot;out.csv&quot;, {encoding: &quot;utf8&quot;}));</code></pre>
425+
<p>When piping from a parser to a formatter the transforms are maintained also.</p>
426+
<pre class='prettyprint linenums lang-js'><code class="lang-javascript">csv
427+
.fromPath(&quot;in.csv&quot;, {headers: true})
428+
.transform(function(obj){
429+
return {
430+
name: obj.Name,
431+
address: obj.Address,
432+
emailAddress: obj.Email_Address,
433+
verified: obj.Verified
434+
};
435+
})
436+
.pipe(csv.createWriteStream({headers: true}))
437+
.pipe(fs.createWriteStream(&quot;out.csv&quot;, {encoding: &quot;utf8&quot;}));</code></pre>
438+
<p>The output will contain formatted result from the transform function.</p>
420439
<h2>Benchmarks</h2>
421440
<p><code>Parsing 20000 records AVG over 3 runs</code></p>
422441
<pre class='prettyprint linenums lang-js'><code>fast-csv: 198.67ms
@@ -438,8 +457,6 @@ <h2>Meta</h2>
438457
<li>Website: <a href="http://c2fo.com">http://c2fo.com</a></li>
439458
<li>Twitter: <a href="http://twitter.com/c2fo"><a href="http://twitter.com/c2fo">http://twitter.com/c2fo</a></a> - 877.465.4045</li>
440459
</ul>
441-
<h2>Namespaces</h2>
442-
<h2>Classes</h2>
443460

444461

445462
<hr>

lib/formatter.js

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
var fs = require("fs"),
2+
util = require("util"),
23
extended = require("./extended"),
34
isUndefinedOrNull = extended.isUndefinedOrNull,
45
hash = extended.hash,
56
stream = require("stream"),
7+
Transform = stream.Transform,
68
LINE_BREAK = extended.LINE_BREAK;
79

810
function createFormatter(options) {
@@ -73,7 +75,7 @@ function wrapWriter(writer, options) {
7375
hasHeaders = extended.has(options, "headers") ? options.headers : true,
7476
parsedHeaders = hasHeaders ? false : true,
7577
headersLength = 0, i = -1,
76-
writerWrite = writer.push, headers,
78+
writerWrite = writer.write, headers,
7779
buffer = [],
7880
totalCount = 0,
7981
MAX_BUFFER_SIZE = options.maxBuffer || 100000;
@@ -82,7 +84,7 @@ function wrapWriter(writer, options) {
8284
if (item) {
8385
var isHash = !extended.isArray(item), vals;
8486
if (!parsedHeaders) {
85-
totalCount++
87+
totalCount++;
8688
parsedHeaders = true;
8789
if (isHash) {
8890
headers = hash.keys(item);
@@ -117,17 +119,32 @@ function wrapWriter(writer, options) {
117119
writerWrite.call(writer, new Buffer(buffer.join("")).toString("utf8"));
118120
buffer.length = 0;
119121
}
120-
writerWrite.call(writer, null);
122+
writer.end();
121123
}
122124
};
123125
return writer;
124126
}
125127

128+
function CsvTransformStream(opts) {
129+
Transform.call(this, opts);
130+
wrapWriter(this, opts);
131+
}
132+
133+
util.inherits(CsvTransformStream, Transform);
134+
135+
extended(CsvTransformStream).extend({
136+
137+
_transform: function (str, encoding, cb) {
138+
cb(null, str);
139+
},
140+
_flush: function (cb) {
141+
this.write(null);
142+
cb(null);
143+
}
144+
});
145+
126146
function createWriteStream(options) {
127-
var writer = new stream.Readable();
128-
writer._read = function () {
129-
};
130-
return wrapWriter(writer, options);
147+
return new CsvTransformStream(options);
131148
}
132149

133150
function write(arr, options) {

0 commit comments

Comments
 (0)