-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathminizlib.ts
More file actions
171 lines (144 loc) · 4.98 KB
/
minizlib.ts
File metadata and controls
171 lines (144 loc) · 4.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/**
* Script to extract compressed files using minizlib
* Features: memory efficient, fast extraction, supports multiple formats
*
* Usage:
* npx ts-node minizlib.ts <input-compressed-file> <output-directory>
*/
import * as fs from 'fs';
import * as path from 'path';
import { Unzip, ZlibOptions } from 'minizlib';
import { promisify } from 'util';
import { pipeline } from 'stream';
const pipelineAsync = promisify(pipeline);
// Get command line arguments
const args = process.argv.slice(2);
if (args.length !== 2) {
console.error('Usage: bun minizlib.ts <input-compressed-file> <output-directory>');
process.exit(1);
}
const inputFile = args[0];
const outputDir = args[1];
// Validate input file exists
if (!fs.existsSync(inputFile)) {
console.error(`Error: Input file "${inputFile}" does not exist.`);
process.exit(1);
}
// Create output directory if it doesn't exist
if (!fs.existsSync(outputDir)) {
try {
fs.mkdirSync(outputDir, { recursive: true });
console.log(`Created output directory: ${outputDir}`);
} catch (err) {
console.error(`Error creating output directory: ${err}`);
process.exit(1);
}
}
// Helper function to format file size
function formatSize(bytes: number): string {
const units = ['B', 'KB', 'MB', 'GB'];
let size = bytes;
let unitIndex = 0;
while (size >= 1024 && unitIndex < units.length - 1) {
size /= 1024;
unitIndex++;
}
return `${size.toFixed(1)} ${units[unitIndex]}`;
}
async function extractCompressed() {
try {
console.log(`Processing ${inputFile}...`);
const startTime = Date.now();
let totalBytes = 0;
// Create read stream for input file
const inputStream = fs.createReadStream(inputFile);
// Create unzip stream with default options
const defaultOptions: ZlibOptions = {
chunkSize: 16 * 1024
};
const unzip = new Unzip(defaultOptions);
// Set up error handlers
inputStream.on('error', (err) => {
console.error(`Error reading input file: ${err}`);
process.exit(1);
});
unzip.on('error', (err) => {
console.error(`Error during decompression: ${err}`);
process.exit(1);
});
// Track progress
let lastProgress = Date.now();
unzip.on('data', (chunk) => {
totalBytes += chunk.length;
// Update progress every 100ms
const now = Date.now();
if (now - lastProgress >= 100) {
const elapsedSeconds = (now - startTime) / 1000;
const bytesPerSecond = totalBytes / elapsedSeconds;
console.log(
`Processed: ${formatSize(totalBytes)} ` +
`(${formatSize(bytesPerSecond)}/sec)`
);
lastProgress = now;
}
});
// Try different decompression methods
try {
console.log('Attempting standard decompression...');
// Method 1: Direct decompression
const outputPath = path.join(outputDir, path.basename(inputFile, '.gz'));
await pipelineAsync(
inputStream,
unzip,
fs.createWriteStream(outputPath)
);
const endTime = Date.now();
const totalTime = (endTime - startTime) / 1000;
console.log('\nDecompression completed!');
console.log(`Output file: ${outputPath}`);
console.log(`Total size: ${formatSize(totalBytes)}`);
console.log(`Time taken: ${totalTime.toFixed(1)} seconds`);
console.log(`Average speed: ${formatSize(totalBytes / totalTime)}/sec`);
return;
} catch (error) {
console.log('Standard decompression failed, trying without header...');
}
// Method 2: Decompression without header
try {
const outputPath = path.join(outputDir, path.basename(inputFile, '.gz'));
const noHeaderOptions: ZlibOptions = {
...defaultOptions,
windowBits: -15 // Negative windowBits means no header
};
await pipelineAsync(
inputStream,
new Unzip(noHeaderOptions),
fs.createWriteStream(outputPath)
);
const endTime = Date.now();
const totalTime = (endTime - startTime) / 1000;
console.log('\nDecompression without header completed!');
console.log(`Output file: ${outputPath}`);
console.log(`Total size: ${formatSize(totalBytes)}`);
console.log(`Time taken: ${totalTime.toFixed(1)} seconds`);
console.log(`Average speed: ${formatSize(totalBytes / totalTime)}/sec`);
return;
} catch (error) {
console.error('All decompression methods failed');
throw error;
}
} catch (err) {
console.error(`Error during extraction: ${err}`);
// Provide more helpful error messages for common issues
if (err instanceof Error) {
if (err.message.includes('invalid') || err.message.includes('not a')) {
console.error('\nThis might be due to:');
console.error('1. File is not compressed or uses unsupported compression');
console.error('2. Corrupted compressed file');
console.error('3. Unsupported compression method');
}
}
process.exit(1);
}
}
extractCompressed();