-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcompress.py
68 lines (51 loc) · 1.72 KB
/
compress.py
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
"""Compresses file."""
import sys
from typing import Dict
from read import Read
from tree import Tree
from write import Write
import math
class FileTooLargeError(Exception):
def __init__(self, message="File is too big"):
self.message = message
super().__init__(self.message)
def main() -> None:
"""Main method for compress.py."""
if len(sys.argv) != 3:
raise ValueError("Invalid number of arguments. Expected exactly two arguments.")
freq_dict: Dict[str, int] = {format(i, '08b'): 0 for i in range(256)}
reader = Read(sys.argv[1])
writer = Write(sys.argv[2])
file_size_zero: bool = reader.file_size == 0
# Gets frequencies of each byte
next_byte = reader.read_byte()
while next_byte is not None:
freq_dict[next_byte] += 1
next_byte = reader.read_byte()
tree = Tree()
# Creates blank file if original file is also blank
if file_size_zero:
with open(sys.argv[2], 'w', encoding='utf-8'):
return
tree.create_tree(freq_dict)
# Create header (right now it is 3 byte header)
bits_needed = math.ceil(math.log(reader.file_size, 2))
if bits_needed > 255:
raise FileTooLargeError("The file is too big to process.")
writer.write_byte(format(bits_needed, '08b'))
print(bits_needed)
for _, value in freq_dict.items():
writer.write_nonstd(format(value, f'0{bits_needed}b'))
writer.reset()
reader.reset_gen()
# Ecodes bytes
curr_byte = ""
while curr_byte is not None:
curr_byte = reader.read_byte()
if curr_byte is None:
break
identifier = curr_byte
tree.encode(identifier, writer)
writer.write_final()
if __name__ == '__main__':
main()