Build a Simple File Compressor with Node.js in 10 Minutes
Have you ever wondered how file compression works? Let's build a simple command-line tool with Node.js that can compress and decompress files. This beginner-friendly project will teach you about streams, one of Node's most powerful features, without overwhelming you with details. What You'll Need Node.js installed on your computer Basic JavaScript knowledge A text editor Project Setup First, create a new folder and set up your project: mkdir file-compressor cd file-compressor npm init -y npm install readline-sync We're using just one package called readline-sync to make it easier to get user input. The Code: Step by Step Create a file called index.js and let's build our compressor piece by piece: Step 1: Import what we need // Import the modules we need const fs = require('fs'); // For working with files const zlib = require('zlib'); // For compression const path = require('path'); // For handling file paths const readlineSync = require('readline-sync'); // For user input // Show a welcome message console.log('==== File Compressor ===='); Step 2: Create our menu // Ask the user what they want to do const choice = readlineSync.question('Do you want to (c)ompress or (d)ecompress a file? '); if (choice.toLowerCase() === 'c') { compressFile(); } else if (choice.toLowerCase() === 'd') { decompressFile(); } else { console.log('Invalid choice. Please enter "c" or "d".'); } Step 3: Create the compression function function compressFile() { // Ask for the file to compress const inputPath = readlineSync.question('Enter the path of the file to compress: '); // Check if the file exists if (!fs.existsSync(inputPath)) { console.log('That file doesn\'t exist. Please check the path and try again.'); return; } // Create output filename const outputPath = inputPath + '.gz'; console.log('Starting compression...'); // Set up our file processing pipeline const readStream = fs.createReadStream(inputPath); const writeStream = fs.createWriteStream(outputPath); const gzip = zlib.createGzip(); // Connect everything together readStream .pipe(gzip) .pipe(writeStream) .on('finish', () => { // Show results when done const originalSize = fs.statSync(inputPath).size; const compressedSize = fs.statSync(outputPath).size; const percentage = ((1 - compressedSize / originalSize) * 100).toFixed(2); console.log('\nCompression complete!'); console.log(`Original size: ${formatSize(originalSize)}`); console.log(`Compressed size: ${formatSize(compressedSize)}`); console.log(`You saved: ${percentage}% of space`); }) .on('error', (err) => { console.log('Something went wrong:', err.message); }); } Step 4: Create the decompression function function decompressFile() { // Ask for the file to decompress const inputPath = readlineSync.question('Enter the path of the compressed file: '); // Check if the file exists if (!fs.existsSync(inputPath)) { console.log('That file doesn\'t exist. Please check the path and try again.'); return; } // Create output filename (remove .gz if present) let outputPath = inputPath.endsWith('.gz') ? inputPath.slice(0, -3) : inputPath + '.decompressed'; console.log('Starting decompression...'); // Set up our file processing pipeline const readStream = fs.createReadStream(inputPath); const writeStream = fs.createWriteStream(outputPath); const gunzip = zlib.createGunzip(); // Connect everything together readStream .pipe(gunzip) .pipe(writeStream) .on('finish', () => { console.log('\nDecompression complete!'); console.log(`Output file: ${outputPath}`); }) .on('error', (err) => { console.log('Something went wrong:', err.message); console.log('This might not be a valid compressed file.'); }); } Step 5: Add a helper function for formatting file sizes // Helper function to format file sizes function formatSize(bytes) { if (bytes

Have you ever wondered how file compression works? Let's build a simple command-line tool with Node.js that can compress and decompress files. This beginner-friendly project will teach you about streams, one of Node's most powerful features, without overwhelming you with details.
What You'll Need
- Node.js installed on your computer
- Basic JavaScript knowledge
- A text editor
Project Setup
First, create a new folder and set up your project:
mkdir file-compressor
cd file-compressor
npm init -y
npm install readline-sync
We're using just one package called readline-sync
to make it easier to get user input.
The Code: Step by Step
Create a file called index.js
and let's build our compressor piece by piece:
Step 1: Import what we need
// Import the modules we need
const fs = require('fs'); // For working with files
const zlib = require('zlib'); // For compression
const path = require('path'); // For handling file paths
const readlineSync = require('readline-sync'); // For user input
// Show a welcome message
console.log('==== File Compressor ====');
Step 2: Create our menu
// Ask the user what they want to do
const choice = readlineSync.question('Do you want to (c)ompress or (d)ecompress a file? ');
if (choice.toLowerCase() === 'c') {
compressFile();
} else if (choice.toLowerCase() === 'd') {
decompressFile();
} else {
console.log('Invalid choice. Please enter "c" or "d".');
}
Step 3: Create the compression function
function compressFile() {
// Ask for the file to compress
const inputPath = readlineSync.question('Enter the path of the file to compress: ');
// Check if the file exists
if (!fs.existsSync(inputPath)) {
console.log('That file doesn\'t exist. Please check the path and try again.');
return;
}
// Create output filename
const outputPath = inputPath + '.gz';
console.log('Starting compression...');
// Set up our file processing pipeline
const readStream = fs.createReadStream(inputPath);
const writeStream = fs.createWriteStream(outputPath);
const gzip = zlib.createGzip();
// Connect everything together
readStream
.pipe(gzip)
.pipe(writeStream)
.on('finish', () => {
// Show results when done
const originalSize = fs.statSync(inputPath).size;
const compressedSize = fs.statSync(outputPath).size;
const percentage = ((1 - compressedSize / originalSize) * 100).toFixed(2);
console.log('\nCompression complete!');
console.log(`Original size: ${formatSize(originalSize)}`);
console.log(`Compressed size: ${formatSize(compressedSize)}`);
console.log(`You saved: ${percentage}% of space`);
})
.on('error', (err) => {
console.log('Something went wrong:', err.message);
});
}
Step 4: Create the decompression function
function decompressFile() {
// Ask for the file to decompress
const inputPath = readlineSync.question('Enter the path of the compressed file: ');
// Check if the file exists
if (!fs.existsSync(inputPath)) {
console.log('That file doesn\'t exist. Please check the path and try again.');
return;
}
// Create output filename (remove .gz if present)
let outputPath = inputPath.endsWith('.gz')
? inputPath.slice(0, -3)
: inputPath + '.decompressed';
console.log('Starting decompression...');
// Set up our file processing pipeline
const readStream = fs.createReadStream(inputPath);
const writeStream = fs.createWriteStream(outputPath);
const gunzip = zlib.createGunzip();
// Connect everything together
readStream
.pipe(gunzip)
.pipe(writeStream)
.on('finish', () => {
console.log('\nDecompression complete!');
console.log(`Output file: ${outputPath}`);
})
.on('error', (err) => {
console.log('Something went wrong:', err.message);
console.log('This might not be a valid compressed file.');
});
}
Step 5: Add a helper function for formatting file sizes
// Helper function to format file sizes
function formatSize(bytes) {
if (bytes < 1024) {
return bytes + ' bytes';
} else if (bytes < 1024 * 1024) {
return (bytes / 1024).toFixed(2) + ' KB';
} else {
return (bytes / (1024 * 1024)).toFixed(2) + ' MB';
}
}
How to Run Your File Compressor
Save your code and run it with:
node index.js
Follow the prompts to compress or decompress a file. Try compressing a text file first - you'll be amazed at how much smaller it gets!
Understanding Streams: The Key Concept
The magic of this program is in this simple line:
readStream.pipe(gzip).pipe(writeStream)
This creates a pipeline where:
-
readStream
reads your file bit by bit - Each bit flows through
gzip
which compresses it - The compressed bits flow to
writeStream
which saves them
Think of it like a water pipe system. The beauty is that you can process files of any size because you're only handling small pieces at a time.
Common Issues You Might Face
- "File not found" error: Make sure you type the full path to your file
- Nothing happens after compression: Large files take time to process, be patient
- The decompressed file doesn't work: Make sure you're decompressing a proper gzip file
What You've Learned
In just a few minutes, you've:
- Created a useful command-line tool
- Learned about Node.js streams
- Used the built-in compression library
- Processed files efficiently
Now you understand one of the most powerful patterns in Node.js! This same approach works for many other types of file processing.
Next Steps
Once you're comfortable with this code, try:
- Adding a progress indicator
- Compressing entire folders
- Supporting different compression levels
Happy coding!