23

For Node.js, what is the best way to prepend to a file in a way SIMILAR to

fs.appendFile(path.join(__dirname, 'app.log'), 'appendme', 'utf8')

Personally, the best way really revolves around a asynchronous solution to create a log where I can basically push onto the file from the top.

Mathew Kurian
  • 5,949
  • 5
  • 46
  • 73

6 Answers6

16

This solution isn't mine and I don't know where it's from but it works.

const data = fs.readFileSync('message.txt')
const fd = fs.openSync('message.txt', 'w+')
const insert = Buffer.from("text to prepend \n")
fs.writeSync(fd, insert, 0, insert.length, 0)
fs.writeSync(fd, data, 0, data.length, insert.length)
fs.close(fd, (err) => {
  if (err) throw err;
});
galki
  • 8,149
  • 7
  • 50
  • 62
  • Great answer - this does indeed work. I used this to prepend a byte-order marker to CSVs I was creating so that Excel would not screw up the encoding on certain characters. – Smitty Aug 29 '18 at 16:10
  • 2
    Awesome! This works well. btw. `Buffer()` is deprecated - use `Buffer.from()` in the above code. –  Mar 02 '21 at 22:00
13

It is impossible to add to a beginning of a file. See this question for the similar problem in C or this question for the similar problem in C#.

I suggest you do your logging in the conventional way (that is, log to the end of file).

Otherwise, there is no way around reading the file, adding the text to the start and writing it back to the file which can get really costly really fast.

Community
  • 1
  • 1
Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
8

It seems it is indeed possible with https://www.npmjs.com/package/prepend-file

ChrisRich
  • 8,300
  • 11
  • 48
  • 67
  • 6
    Note: That does not work as advertized - the complexity of the operation depends on the file size - prepending to a 4gb file will copy 4gb of data around. – Benjamin Gruenbaum Aug 12 '16 at 20:04
  • 2
    @BenjaminGruenbaum it was advertised as prepending to a file and it works perfectly for me. – tadasajon Sep 11 '17 at 20:39
  • 2
    Well, it probably works as advertised, but in some cases is not going to be a good idea! – Josh M. Mar 07 '19 at 18:11
  • 1
    I agree with @BenjaminGruenbaum: this is not "prepending" this is copying the entire file in order to 'prepend'. – Nir Alfasi Feb 28 '21 at 10:48
1

Here is an example of how to prepend text to a file using gulp and a custom built function.

var through = require('through2');

gulp.src('somefile.js')
     .pipe(insert('text to prepend with'))
     .pipe(gulp.dest('Destination/Path/'))


function insert(text) {
    function prefixStream(prefixText) {
        var stream = through();
        stream.write(prefixText);
        return stream;
    }

    let prefixText = new Buffer(text + "\n\n"); // allocate ahead of time

    // creating a stream through which each file will pass
    var stream = through.obj(function (file, enc, cb) {
        //console.log(file.contents.toString());

        if (file.isBuffer()) {
            file.contents = new Buffer(prefixText.toString() + file.contents.toString());
        }

        if (file.isStream()) {
            throw new Error('stream files are not supported for insertion, they must be buffered');
        }

        // make sure the file goes through the next gulp plugin
        this.push(file);
        // tell the stream engine that we are done with this file
        cb();
    });

    // returning the file stream
    return stream;    
}

Sources: [cole_gentry_github_dealingWithStreams][1]

Isaac Adams
  • 150
  • 4
0

Its possible by using the prepend-file node module. Do the following:

  1. npm i prepend-file -S
  2. import prepend-file module in your respective code.

Example:

let firstFile = 'first.txt';
let secondFile = 'second.txt';
prependFile(firstFile, secondFile, () => {
  console.log('file prepend successfully');
})
SalmonKiller
  • 2,183
  • 4
  • 27
  • 56
  • 1
    Hey Chandra, can you please explain what the `-S` option for the `npm install` command does? I can't seem to find it in the documentation. – SalmonKiller Mar 14 '19 at 05:05
  • @SalmonKiller Prior to [npm-5](https://blog.npmjs.org/post/161081169345/v500), `npm install` would just install the package without adding it to your `package.json` file. `-S` is short for `--save`. Starting with npm-5, this option is called `-P` or `--save-prod`. You would use `--no-save` if you didn’t want the package added to `package.json` (i.e., it’s now opt-out). – binki Sep 22 '19 at 18:09
0

This method can also be an alternative:

fs.readFile(path.dirname(__filename) + '/read.txt', 'utf8', function (err, data) {
  fs.writeFile(path.dirname(__filename) + '/read.text', 'prepend text' + data, (err) => {
        
  })
});
Tyler2P
  • 2,324
  • 26
  • 22
  • 31