
How it works...
The I/O channels (STDOUT, STDERR, STDIN) are implemented using Node.js streams.
We'll find out more about Node.js streams in Chapter 4, Using Streams. We also have an example in the There's more... section of this recipe, regarding using the standard I/O channels as streams.
Suffice it to say, that Node Stream instances (instantiated from Node's core stream module) inherit from EventEmitter (from Node's core events module), and emit a data event for every chunk of data received.
When in interactive mode (that is, when inputting via the keyboard), each data chunk is determined by a newline. When piping data through to the process, each data chunk is determined by the maximum memory consumption allowable for the stream (this is determined by the highWaterMark, but we'll learn more about this in Chapter 4, Using Streams).
We listen to the data event, which provides a Buffer object (also called data) holding a binary representation of the input.
We write to STDERR (standard error) first, simply by passing a string, process.stderr.write. The string contains the data Buffer object, which is automatically converted to a string representation when interpolated into (or concatenated with) another string.
Next we write to STDOUT (standard output), using process.stdout.write. The Buffer objects have a toString method that can be passed an encoding option. We specify an encoding of base64 when calling toString on the buffer object, to convert the input from raw binary data to a base64 string representation.