node-csv
node-csv copied to clipboard
Missing header in output when input has only header
Hi there,
The following code
const inputFilePath = 'test_in.csv';
const outputCsv = fs.createWriteStream('test_out.csv');
fs.createReadStream(inputFilePath)
.pipe(csv.parse({ columns: true }))
.pipe(csv.stringify({ header: true, quoted: true }))
.pipe(outputCsv);
Gives the output I expect (output same as input, apart from the quotes) when the input has lines beyond the header, but gives an empty file instead when test_in.csv only contains a header. Is that expected? How can I force it to always dump the header to the output?
Many thanks in advance.
To make sure I understand, please provide a sample input, the actual output and the expected output.
Hi @wdavidw ,
Thanks for the quick reply. The sample inputs are:
- expected behaviour case
test_in.csv:
Co1,Col2,Col3
1,2,3
(the corresponding output I get is
"Co1","Col2","Col3"
"1","2","3"
- unexpected behaviour case
test_in.csv:
Co1,Col2,Col3
output: empty file.
ok, I get it. Don't know if we shall classify this as a bug, a missing feature, or even as a breaking change. This will have an impact on the visioning and potentially some angry users who might disagree. I tend to consider this as a bug.
I believe that it ought to be treated as a bug based on this previous ticket (which I came across while researching this problem): https://github.com/adaltas/node-csv/issues/66
But having said that, if you have any suggestions for a quick fix, I would be most grateful :grinning: I would like to avoid having to count lines in the input files and decide what to do based on that.
if a bug and a fix exist, even if it was years ago, I am surprised it is still there. Let me look at the code
It seems like it is not a bug nor anything else, there is not much we can do about. The problem is not in the parser nor in the stringifier. You can see that it is implemented in the stringifier here.
You problem is that first, you parse the data with {column: true} and this return no records since there are none. Your solution is not to treat headers as such in parse, only when you stringify, eg:
fs.createReadStream(inputFilePath)
.pipe(csv.parse())
.pipe(csv.stringify({ header: true, quoted: true }))
.pipe(outputCsv);
When I try with that, I get
Error: Undiscoverable Columns: header option requires column option or object records
at Stringifier._transform (/home/kerim/abtrace/GPAppTPP/node_modules/csv-stringify/lib/index.js:212:27)
at Stringifier.Transform._read (_stream_transform.js:191:10)
at Stringifier.Transform._write (_stream_transform.js:179:12)
at doWrite (_stream_writable.js:403:12)
at writeOrBuffer (_stream_writable.js:387:5)
at Stringifier.Writable.write (_stream_writable.js:318:11)
at Parser.ondata (_stream_readable.js:717:22)
at Parser.emit (events.js:315:20)
at addChunk (_stream_readable.js:295:12)
at readableAddChunk (_stream_readable.js:271:9)
(for both input files, not just the header-only one)
Do you really need headers, you could just
fs.createReadStream(inputFilePath)
.pipe(csv.parse())
.pipe(csv.stringify({ quoted: true }))
.pipe(outputCsv);
Otherwise, you'll have to work around the stream API (or use the sync one), you can leverage transform to extract columns (https://csv.js.org/project/examples/#using-the-pipe-api) and re-inject it.
Could we close the issue ?