Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

createWriteStream; close doesn't finish writing all data to file #5631

Closed
d3x0r opened this issue Mar 9, 2016 · 8 comments
Closed

createWriteStream; close doesn't finish writing all data to file #5631

d3x0r opened this issue Mar 9, 2016 · 8 comments
Labels
fs Issues and PRs related to the fs subsystem / file system. question Issues that look for answers. stream Issues and PRs related to the stream subsystem.

Comments

@d3x0r
Copy link
Contributor

d3x0r commented Mar 9, 2016

Windows 7/10,
node 5.6.0, and latest builds...
This seems like something fairly critical...

"use strict";

const fs = require( 'fs' );
var outData = fs.createWriteStream( "output.txt" );
outData.write( "line one" );
outData.write( "line two" );
outData.close();

results in a file that only has 'line one' in it.
it can be several lines... I'm often missing 5 lines in this one file... but basically every file never writes all information to the file.

this might be similar to #2314

@d3x0r d3x0r changed the title createWriteStream doesn't finish writing all data to file createWriteStream; close doesn't finish writing all data to file Mar 9, 2016
@Fishrock123 Fishrock123 added fs Issues and PRs related to the fs subsystem / file system. stream Issues and PRs related to the stream subsystem. labels Mar 9, 2016
@evanlucas
Copy link
Contributor

Here is a working example. In order to have a guarantee that write() has finished, you must wait for the callback on it.

'use strict'

const fs = require('fs')
const stream = fs.createWriteStream('out.txt')
stream.write('line one', () => {
  stream.write('line two', () => {
    stream.close()
  }) 
})

@Fishrock123 Fishrock123 added the question Issues that look for answers. label Mar 9, 2016
@d3x0r
Copy link
Contributor Author

d3x0r commented Mar 9, 2016

Okay I started to dig into the code, and added some console.log( stream ); after the writes.... there's a 'pendingcb' which goes up, and things start to get buffered... so I supposed maybe if there wasn't a callback it would fail.

It will take some time to restructure the code to fit HAVING to use the callbacks.
I would still think that close operation should pend itself after the writes, or mark the stream as closed so the last write can complete the close....

but even in a more complex case where I continue on to do other work with other files for a long amount of time the output still doesn't go... so the pending writes apparently never get called without having a callback of some sort...

@Slayer95
Copy link

Slayer95 commented Mar 9, 2016

@d3x0r , maybe you are looking for WritableStream#end() ? That will automatically handle closing the stream for you after pending writes are done.

Note that close() is not part of the public API (https://nodejs.org/api/stream.html#stream_class_stream_writable)

@d3x0r
Copy link
Contributor Author

d3x0r commented Mar 9, 2016

I had added

outData.write( "line two" );
outData.end();
outData.close();

but that made no difference.

@vkurchatkin
Copy link
Contributor

This works as expected. close immediately closes fd without flushing ending writes. Just call end and fd will be closed automatically after writes are flushed.

@d3x0r
Copy link
Contributor Author

d3x0r commented Mar 9, 2016

confirmed; replacing close with end lets it work :)

@ORESoftware
Copy link
Contributor

close() is no longer a method on the writable instance, use end() instead

@seantcanavan
Copy link

seantcanavan commented Oct 26, 2021

is there no way to use await or anything like that in conjunction with end() to halt the process and wait for the memory buffer to write to the file? i'm trying to email a CSV and it keeps going out without its full contents. I'm assuming because writing is still queue'd after end() and also after my sendEmail call happens. the question is why after calling end() does it take my local process exiting to get the full file output? I've verified locally that the attachment has all the correct contents. It's just while executing the file must not be finished before getting email.

EDIT: Solution is here: nodejs/help#1641 (comment) credit to @provCristianMaluenda:

        // create the output file
        const csvFileName = 'invoice_report_' + getUnixFriendlyTimestampString() + '.csv';
        const csvFilePath = '/tmp/' + csvFileName;
        const writeStream = fs.createWriteStream(csvFilePath, { flags: 'a' });
        const csvWriteStream = format({ headers: true, delimiter: ',' });

        // pipe data from the stream to the newly created file
        csvWriteStream.pipe(writeStream);```
...
...
        // write final CSV output line
        csvWriteStream.write({
            totalDollarAmount: totalDollarAmount.toString()
        });

        // close the file handle and wait for memory buffer to be written to disk
        await this.waitForStreamClose(writeStream);
        sendGrid.sendEmail(to, from, [csvFileName]); // email sends with full file content now
...
...
    async waitForStreamClose(stream: WriteStream): Promise<void> {
        stream.end();
        return new Promise((resolve) => {
            stream.once('finish', () => {
                resolve();
            });
        });
    }


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fs Issues and PRs related to the fs subsystem / file system. question Issues that look for answers. stream Issues and PRs related to the stream subsystem.
Projects
None yet
Development

No branches or pull requests

7 participants