Question

I am writing an object that exposes a function that appends a string to the end of a file ensuring that:

1- file is written to immediately. 2- the program has an exclusive lock on the file. 3- the lock is persistent between writes

I am using fs.open fs.write and buffer, because Streams seem too complicated. I assume I would have to flush after a write if I used a stream.

Is it possible to call fs.write() and fs.writeSync() without most of the options.

/* What I would like to do is this: */

buffer = new Buffer( string, encoding );
fs.write( fd, buffer, callback );
fs.writeSync( fd, buffer );

// Failing that I would like to know which of these is correct:

fs.write( fd, buffer, 0, buffer.length, null, callback );
fs.write( fd, buffer, 0, string.length, null, callback );
Was it helpful?

Solution

Ok so I did some testing and came up with the following code, which assumes the file doesn't exist (it will throw an exception because of the x flag if it does):

var fs = require("fs");
var log = {

    filename: "path",
    flag: "ax",
    mode: 0444,
    file: null,
    encoding: "utf8",
    finalMode: 0644,

    write: function( string ) {
        if( this.file == null ) {

            this.file = fs.openSync(this.filename, this.flag, this.mode);

        }
        if( string instanceof String ) string = string.toString();
        if( typeof string != "string" ) string = JSON.stringify( string );
        var buffer = new Buffer( string, this.encoding );
        fs.writeSync(this.file, buffer, 0, buffer.length);
        return this;
    },
    close: function() {
        fs.close(this.file);
        if( this.finalMode != this.mode ) {
            fs.chmod(this.filename, this.finalMode);
        }
        return this;
    }
}

log.write("Hello World!\n").write("Goodbye World!\n").close();

This code can't always guarantee "Hello World!" would be written before "Goodbye World!" if fs.write() is used instead of fs.writeSync(). I have tested this extensively and have only had one occasion where the order was wrong. I inserted a sequence of chunks with size s/(2^n) so the first chunk was 256kb and the next 128kb down to 1kb and in one trial run the first chunk was inserted last instead of first and all the other chunks were in order. Chunk integrity was preserved as well throughout the tests. Results may differ on your system based on hardware, software and load. For logging purposes not being in order is not terrible as each chunk can (and should) be prepended with a timestamp.

What is clear is that:

  1. Offset and length are required and will cause exceptions if left empty.
  2. Offset and length are in bytes.
  3. Buffer.length must be used, like in the question's first example. Even though most of the time string.length == buffer.length if encoding is utf8 it is better not to use the second example.
  4. Position can be undefined (not provided in the function call) and will behave as if null (no strong equality in the function)
  5. Callback can be undefined (as specified in documentation)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top