As a full-stack JavaScript developer, I often need to read and write files in Node.js applications. While Node.js prefers asynchronous file I/O for performance reasons, sometimes synchronous file operations make sense for simplicity or when performance is not critical.

In this comprehensive guide, we‘ll explore how to write files synchronously in Node.js using the fs.writeFileSync() method.

Overview of fs.writeFileSync()

The fs module in Node.js contains methods for interacting with the file system. The fs.writeFileSync() method writes data to a file synchronously. Some key things to know:

  • It blocks the event loop until the file write is complete
  • Automatically creates the file if it doesn‘t exist
  • Overwrites existing file content by default
  • Useful for scripts that need to write a file and move on

The signature is:

fs.writeFileSync(file, data[, options])
  • file – File path or descriptor to write to
  • data – String or buffer with data to write
  • options – Additional options like encoding

Let‘s look at some examples of using fs.writeFileSync() to write files synchronously.

Write a File with Default Options

This writes a string to a new file called test.txt:

const fs = require(‘fs‘);

let content = ‘Hello World!‘;

fs.writeFileSync(‘test.txt‘, content);

By default, this will:

  • Create test.txt if it doesn‘t exist
  • Overwrite test.txt if it already exists
  • Write the content as a UTF-8 encoded string

This is the simplest way to use fs.writeFileSync() with all default options.

Specify Encoding Options

You can specify custom encoding with the options parameter:

let content = ‘Some file content‘;

let options = {encoding:‘ascii‘};

fs.writeFileSync(‘file.txt‘, content, options); 

Some supported encoding types are ‘utf8‘, ‘ascii‘, ‘utf16le‘ etc.

This writes the content as ASCII instead of UTF-8.

Write a Buffer Instead of a String

You can write a Buffer object instead of a string:

let buf = Buffer.from(‘Hello‘); 

fs.writeFileSync(‘buffer.txt‘, buf);

This can be useful for writing binary data.

Append Data to an Existing File

By default fs.writeFileSync() overwrites the specified file. To append instead pass the flag option:

fs.writeFileSync(‘messages.log‘, ‘Log message 1‘, {flag:‘a‘}); 

// Later append another message
fs.writeFileSync(‘messages.log‘, ‘Log message 2‘, {flag:‘a‘}); 

This will write "Log message 1" then append "Log message 2" on the next line.

Write a Large File Using Buffered Writes

For large files, use a stream instead for better memory performance:

let writer = fs.createWriteStream(‘largefile.txt‘);

writer.write(‘Part1 ‘); 
writer.write(‘Part2 ‘);
writer.end(); 

But if you need synchronous writes, use a buffer & loop:

let buf = Buffer.alloc(2048);
let len;

do {
  len = fs.writeSync(fd, buf, 0, buf.length);
} while (len === buf.length);

This efficiently appends data from a buffer in chunks.

Error Handling

fs.writeFileSync() throws errors if there is a problem writing the file:

try {
  fs.writeFileSync(‘data.json‘, content);  
} catch (err) {
  // Handle error
  console.error(‘Write failed: ‘ + err);
}

This catches errors like invalid paths, permissions issues etc.

You can also handle errors in the callback:

fs.writeFile(‘file.txt‘, data, (err) => {
  if (err) console.log(err);
});

Concurrency Considerations

Since fs.writeFileSync() blocks the event loop, calls will happen sequentially.

For example this will take at least 2 seconds:

fs.writeFileSync(‘file1.txt‘, ‘Hello‘, { encoding: ‘utf8‘ }); // 1 second
fs.writeFileSync(‘file2.txt‘, ‘World‘, { encoding: ‘utf8‘ }); // 1 second 

So only use synchronous file operations if performance is not a major factor.

Key Benefits

Some benefits of fs.writeFileSync():

  • Simple synchronous file writing interface
  • Automatically creates files if they don‘t exist
  • Useful for configuration files needed at startup
  • Avoid race conditions in scripts that use the written file right after

In short, it trades some performance to make it easier to write files reliably.

Conclusion

In this guide, we looked at how fs.writeFileSync() enables you to write files synchronously in Node.js. Some key points:

  • Blocks event loop until file write finishes
  • Accepts file path, data and options like encoding
  • Can append data or overwrite existing files
  • Handles error cases like invalid paths
  • Trades some concurrency for code simplicity

So in cases where you need reliable file writing or concurrency is not critical, fs.writeFileSync() can be very useful.

I hope you found this guide helpful! Let me know if you have any other questions about synchronous file I/O in Node.js.

Similar Posts