-
Notifications
You must be signed in to change notification settings - Fork 0
/
input.txt
218 lines (164 loc) · 6.98 KB
/
input.txt
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
### **Understanding the Combined Rust Compression & Decompression Script**
#### **High-Level Overview**
This Rust script combines two core functionalities:
1. **Compression**: Taking an input file, compressing it using the Gzip algorithm, and writing the compressed content to a target file.
2. **Decompression**: Reading a previously compressed file (in `.gz` format), decompressing its content, and restoring it to its original state in a target file.
The script uses the **`flate2` crate**, a library for handling Gzip, Deflate, and Zlib compression formats in Rust.
---
#### **How the Script Works: Step-by-Step**
##### **1. Command-Line Argument Parsing**
At runtime, the program expects the user to provide:
- **Mode**: Either `compress` or `decompress`.
- **Source File**: The file to compress or decompress.
- **Target File**: The output file where results will be stored.
Example:
```bash
cargo run -- compress input.txt output.gz
cargo run -- decompress output.gz restored.txt
```
- The script checks that the correct number of arguments is passed using:
```rust
let args: Vec<String> = args().collect();
if args.len() != 4 {
eprintln!("Usage: compress|decompress <source> <target>");
return;
}
```
##### **2. Mode Selection**
The program reads the **first argument** (mode) and matches it:
- If the mode is `"compress"`, the script calls the `compress` function.
- If the mode is `"decompress"`, it calls the `decompress` function.
- If an invalid mode is provided, it prints an error.
This is done using a `match` statement:
```rust
match mode.as_str() {
"compress" => { compress(source, target); }
"decompress" => { decompress(source, target); }
_ => { eprintln!("Invalid mode."); }
}
```
---
#### **Compression Logic: High-Level to Low-Level**
1. **Open Source File**:
- The source file is opened using `File::open()` and wrapped in a **buffered reader** for efficiency.
- A `BufReader` minimizes system calls by reading data in chunks.
```rust
let input = BufReader::new(File::open(source).expect("Failed to open source file"));
```
2. **Create Target File**:
- The target file (compressed output) is created using `File::create`.
```rust
let output = File::create(target).expect("Failed to create target file");
```
3. **Initialize Gzip Encoder**:
- The `GzEncoder` struct (from the `flate2` crate) wraps the target file and compresses any data written to it using the **Gzip algorithm**.
```rust
let mut encoder = GzEncoder::new(output, Compression::default());
```
4. **Copy Data**:
- Data from the source file is copied to the Gzip encoder using the `copy` function. This is efficient and automatically handles reading and writing.
```rust
copy(&mut input.clone(), &mut encoder).expect("Failed to compress file");
```
5. **Finalize Compression**:
- The `encoder.finish()` function ensures all compressed data is flushed and written to the output file.
```rust
let output = encoder.finish().expect("Failed to finalize compression");
```
6. **Report Results**:
- The script measures and displays:
- The **original size** of the source file.
- The **compressed size** of the output file.
- The **time taken** for compression.
```rust
println!("Compression completed in {:?}", start.elapsed());
```
---
#### **Decompression Logic: High-Level to Low-Level**
1. **Open Compressed Source File**:
- The `.gz` file is opened using `File::open()`.
```rust
let input_file = File::open(source).expect("Failed to open compressed file");
```
2. **Initialize Gzip Decoder**:
- The `GzDecoder` wraps the compressed file and decompresses its contents as they are read.
```rust
let mut decoder = GzDecoder::new(input_file);
```
3. **Create Target File**:
- The decompressed data will be written to this target file.
```rust
let mut output_file = File::create(target).expect("Failed to create target file");
```
4. **Copy Data**:
- Data is copied from the Gzip decoder to the target file using the `copy` function.
```rust
copy(&mut decoder, &mut output_file).expect("Failed to decompress file");
```
5. **Report Results**:
- The script measures and reports:
- The **size** of the decompressed file.
- The **time taken** for decompression.
```rust
println!("Decompression completed in {:?}", start.elapsed());
```
---
#### **Key Libraries and Concepts Used**
1. **`flate2` Crate**:
- Provides Gzip compression (`GzEncoder`) and decompression (`GzDecoder`).
- Supports different compression levels (`Compression::default()`).
2. **`std::fs` Module**:
- `File::open()` and `File::create()` handle file input/output operations.
3. **`std::io` Module**:
- `BufReader` optimizes file reading.
- `copy()` is used for efficient data transfer.
4. **Command-Line Argument Handling**:
- The `std::env::args` function reads arguments passed to the program.
5. **Time Measurement**:
- `std::time::Instant` is used to calculate the duration of compression/decompression.
---
#### **Summary**
This Rust script:
1. Accepts user input to determine whether to **compress** or **decompress** a file.
2. Uses the `flate2` crate for Gzip-based compression and decompression.
3. Ensures efficient file handling with `BufReader` and `copy`.
4. Reports relevant details like file sizes and execution time to provide clear feedback.
---
You can copy this explanation directly into your `input.txt` file to test the script:
```plaintext
Understanding the Combined Rust Compression & Decompression Script
High-Level Overview:
This Rust script combines two core functionalities:
1. Compression: Taking an input file, compressing it using the Gzip algorithm, and writing the compressed content to a target file.
2. Decompression: Reading a previously compressed file (in .gz format), decompressing its content, and restoring it to its original state.
The script uses the `flate2` crate for Gzip compression and decompression.
Core Steps:
1. Command-line arguments specify the mode, source file, and target file.
2. For compression:
- Read data from the source file.
- Compress the data with Gzip and save it to a target file.
3. For decompression:
- Read the compressed file.
- Decompress its data and save it to a target file.
4. The script reports file sizes and execution time for clarity.
Libraries Used:
- flate2: Provides GzEncoder for compression and GzDecoder for decompression.
- std::fs: Handles file I/O operations.
- std::io: Ensures efficient data transfer using BufReader and copy().
- std::time: Measures execution time.
Usage:
- Compress: cargo run -- compress input.txt output.gz
- Decompress: cargo run -- decompress output.gz restored.txt
```
---
### Steps to Test:
1. Save this explanation as `input.txt`.
2. Run the compression command:
```bash
cargo run -- compress input.txt compressed.gz
```
3. Run the decompression command:
```bash
cargo run -- decompress compressed.gz output.txt
```
4. Verify that `output.txt` matches the original `input.txt`.