Skip to content

Commit ca56ddf

Browse files
committed
Adding the file zipper files
1 parent 83afa6b commit ca56ddf

7 files changed

Lines changed: 390 additions & 0 deletions

File tree

assets/Images/File_Zipper.jpeg

67.5 KB
Loading

assets/css/File_Zipper.css

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
html,
2+
body {
3+
height: 100%;
4+
}
5+
6+
.text_box {
7+
padding: 30px;
8+
width: 50%;
9+
height: 100%;
10+
border: 1px solid lightgray;
11+
display: flex;
12+
flex-wrap: wrap;
13+
align-content: center;
14+
}
15+
16+
#container{
17+
width: 100%;
18+
height: 70%;
19+
background-color: white;
20+
display: flex;
21+
margin: 0 auto;
22+
}
23+
24+
.center_buttons{
25+
margin:auto;
26+
display:block;
27+
}

assets/js/File_Zipper_js/heap.js

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/**
2+
* Created by aarnavjindal on 30/03/20.
3+
*/
4+
5+
export { BinaryHeap }
6+
7+
class BinaryHeap {
8+
9+
constructor() {
10+
this.heap = [];
11+
}
12+
13+
insert(value) {
14+
this.heap.push(value);
15+
this.bubbleUp();
16+
}
17+
18+
size() {
19+
return this.heap.length;
20+
}
21+
22+
empty(){
23+
return ( this.size()===0 );
24+
}
25+
26+
//using iterative approach
27+
bubbleUp() {
28+
let index = this.size() - 1;
29+
30+
while (index > 0) {
31+
let element = this.heap[index],
32+
parentIndex = Math.floor((index - 1) / 2),
33+
parent = this.heap[parentIndex];
34+
35+
if (parent[0] >= element[0]) break;
36+
this.heap[index] = parent;
37+
this.heap[parentIndex] = element;
38+
index = parentIndex
39+
}
40+
}
41+
42+
extractMax() {
43+
const max = this.heap[0];
44+
const tmp = this.heap.pop();
45+
if(!this.empty()) {
46+
this.heap[0] = tmp;
47+
this.sinkDown(0);
48+
}
49+
return max;
50+
}
51+
52+
sinkDown(index) {
53+
54+
let left = 2 * index + 1,
55+
right = 2 * index + 2,
56+
largest = index;
57+
const length = this.size();
58+
59+
// console.log(this.heap[left], left, length, this.heap[right], right, length, this.heap[largest]);
60+
61+
if (left < length && this.heap[left][0] > this.heap[largest][0]) {
62+
largest = left
63+
}
64+
if (right < length && this.heap[right][0] > this.heap[largest][0]) {
65+
largest = right
66+
}
67+
// swap
68+
if (largest !== index) {
69+
let tmp = this.heap[largest];
70+
this.heap[largest] = this.heap[index];
71+
this.heap[index] = tmp;
72+
this.sinkDown(largest)
73+
}
74+
}
75+
}
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/**
2+
* Created by aarnavjindal on 25/04/20.
3+
*/
4+
5+
import { BinaryHeap } from './heap.js';
6+
7+
export { HuffmanCoder }
8+
9+
class HuffmanCoder{
10+
11+
stringify(node){
12+
if(typeof(node[1])==="string"){
13+
return '\''+node[1];
14+
}
15+
16+
return '0' + this.stringify(node[1][0]) + '1' + this.stringify(node[1][1]);
17+
}
18+
19+
display(node, modify, index=1){
20+
if(modify){
21+
node = ['',node];
22+
if(node[1].length===1)
23+
node[1] = node[1][0];
24+
}
25+
26+
if(typeof(node[1])==="string"){
27+
return String(index) + " = " + node[1];
28+
}
29+
30+
let left = this.display(node[1][0], modify, index*2);
31+
let right = this.display(node[1][1], modify, index*2+1);
32+
let res = String(index*2)+" <= "+index+" => "+String(index*2+1);
33+
return res + '\n' + left + '\n' + right;
34+
}
35+
36+
destringify(data){
37+
let node = [];
38+
if(data[this.ind]==='\''){
39+
this.ind++;
40+
node.push(data[this.ind]);
41+
this.ind++;
42+
return node;
43+
}
44+
45+
this.ind++;
46+
let left = this.destringify(data);
47+
node.push(left);
48+
this.ind++;
49+
let right = this.destringify(data);
50+
node.push(right);
51+
52+
return node;
53+
}
54+
55+
getMappings(node, path){
56+
if(typeof(node[1])==="string"){
57+
this.mappings[node[1]] = path;
58+
return;
59+
}
60+
61+
this.getMappings(node[1][0], path+"0");
62+
this.getMappings(node[1][1], path+"1");
63+
}
64+
65+
encode(data){
66+
67+
this.heap = new BinaryHeap();
68+
69+
const mp = new Map();
70+
for(let i=0;i<data.length;i++){
71+
if(data[i] in mp){
72+
mp[data[i]] = mp[data[i]] + 1;
73+
} else{
74+
mp[data[i]] = 1;
75+
}
76+
}
77+
78+
for(const key in mp){
79+
this.heap.insert([-mp[key], key]);
80+
}
81+
82+
while(this.heap.size() > 1){
83+
const node1 = this.heap.extractMax();
84+
const node2 = this.heap.extractMax();
85+
86+
const node = [node1[0]+node2[0],[node1,node2]];
87+
this.heap.insert(node);
88+
}
89+
const huffman_encoder = this.heap.extractMax();
90+
91+
this.mappings = {};
92+
this.getMappings(huffman_encoder, "");
93+
94+
let binary_string = "";
95+
for(let i=0;i<data.length;i++) {
96+
binary_string = binary_string + this.mappings[data[i]];
97+
}
98+
99+
let rem = (8 - binary_string.length%8)%8;
100+
let padding = "";
101+
for(let i=0;i<rem;i++)
102+
padding = padding + "0";
103+
binary_string = binary_string + padding;
104+
105+
let result = "";
106+
for(let i=0;i<binary_string.length;i+=8){
107+
let num = 0;
108+
for(let j=0;j<8;j++){
109+
num = num*2 + (binary_string[i+j]-"0");
110+
}
111+
result = result + String.fromCharCode(num);
112+
}
113+
114+
let final_res = this.stringify(huffman_encoder) + '\n' + rem + '\n' + result;
115+
let info = "Compression Ratio : " + data.length/final_res.length;
116+
info = "Compression complete and file sent for download" + '\n' + info;
117+
return [final_res, this.display(huffman_encoder, false), info];
118+
}
119+
120+
decode(data){
121+
data = data.split('\n');
122+
if(data.length===4){
123+
// Handling new line
124+
data[0] = data[0] + '\n' + data[1];
125+
data[1] = data[2];
126+
data[2] = data[3];
127+
data.pop();
128+
}
129+
130+
this.ind = 0;
131+
const huffman_decoder = this.destringify(data[0]);
132+
const text = data[2];
133+
134+
let binary_string = "";
135+
for(let i=0;i<text.length;i++){
136+
let num = text[i].charCodeAt(0);
137+
let bin = "";
138+
for(let j=0;j<8;j++){
139+
bin = num%2 + bin;
140+
num = Math.floor(num/2);
141+
}
142+
binary_string = binary_string + bin;
143+
}
144+
binary_string = binary_string.substring(0,binary_string.length-data[1]);
145+
146+
console.log(binary_string.length);
147+
148+
let res = "";
149+
let node = huffman_decoder;
150+
for(let i=0;i<binary_string.length;i++){
151+
if(binary_string[i]==='0'){
152+
node = node[0];
153+
} else{
154+
node = node[1];
155+
}
156+
157+
if(typeof(node[0])==="string"){
158+
res += node[0];
159+
node = huffman_decoder;
160+
}
161+
}
162+
let info = "Decompression complete and file sent for download";
163+
return [res, this.display(huffman_decoder, true), info];
164+
}
165+
}

assets/js/File_Zipper_js/script.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { HuffmanCoder } from './huffman.js';
2+
3+
4+
onload = function () {
5+
// Get reference to elements
6+
const treearea = document.getElementById('treearea');
7+
const encode = document.getElementById('encode');
8+
const decode = document.getElementById('decode');
9+
const temptext = document.getElementById('temptext');
10+
const upload = document.getElementById('uploadedFile');
11+
12+
const coder = new HuffmanCoder();
13+
14+
upload.addEventListener('change',()=>{ alert("File uploaded") });
15+
16+
encode.onclick = function () {
17+
18+
const uploadedFile = upload.files[0];
19+
if(uploadedFile===undefined){
20+
alert("No file uploaded !");
21+
return;
22+
}
23+
const fileReader = new FileReader();
24+
fileReader.onload = function(fileLoadedEvent){
25+
const text = fileLoadedEvent.target.result;
26+
if(text.length===0){
27+
alert("Text can not be empty ! Upload another file !");
28+
return;
29+
}
30+
let [encoded, tree_structure, info] = coder.encode(text);
31+
downloadFile(uploadedFile.name.split('.')[0] +'_encoded.txt', encoded);
32+
treearea.innerText = tree_structure;
33+
treearea.style.marginTop = '2000px';
34+
temptext.innerText = info;
35+
};
36+
fileReader.readAsText(uploadedFile, "UTF-8");
37+
};
38+
39+
decode.onclick = function () {
40+
41+
const uploadedFile = upload.files[0];
42+
if(uploadedFile===undefined){
43+
alert("No file uploaded !");
44+
return;
45+
}
46+
const fileReader = new FileReader();
47+
fileReader.onload = function(fileLoadedEvent){
48+
const text = fileLoadedEvent.target.result;
49+
if(text.length===0){
50+
alert("Text can not be empty ! Upload another file !");
51+
return;
52+
}
53+
let [decoded, tree_structure, info] = coder.decode(text);
54+
downloadFile(uploadedFile.name.split('.')[0] +'_decoded.txt', decoded);
55+
treearea.innerText = tree_structure;
56+
treearea.style.marginTop = '2000px';
57+
temptext.innerText = info;
58+
};
59+
fileReader.readAsText(uploadedFile, "UTF-8");
60+
};
61+
62+
};
63+
64+
function downloadFile(fileName, data){
65+
let a = document.createElement('a');
66+
a.href = "data:application/octet-stream,"+encodeURIComponent(data);
67+
a.download = fileName;
68+
a.click();
69+
}

public/File_Zipper.html

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7+
<title>Document</title>
8+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
9+
10+
<link rel="stylesheet" href='../assets/css/File_Zipper.css'>
11+
<script src='../assets/css/File_Zipper.css'></script>
12+
<script src="../assets/js/File_Zipper_js.js" type="module"></script>
13+
<script src="../assets/js/File_Zipper_js.js" type="module"></script>
14+
</head>
15+
16+
<body>
17+
<nav class="navbar navbar-light " style="font-size: 25px; font-family: sans-serif; background-color: whitesmoke;">
18+
19+
20+
File Zipper using huffman Encoding and Decoding
21+
</nav>
22+
<div id="container">
23+
<div class="text_box" style="overflow-y: scroll">
24+
<span id="treearea" style="width: 100%; text-align: center; font-size: medium;">
25+
Tree Structure Will Be Displayed Here !!
26+
</span>
27+
</div>
28+
<div class="text_box" style="overflow-y: scroll">
29+
<span id="temptext" style="width: 100%; text-align: center; font-size: x-large;">
30+
Operation info will be shown here !!
31+
</span>
32+
</div>
33+
</div>
34+
35+
<div>
36+
<form method="post" enctype="multipart/form-data" style="display: inline-block;">
37+
<input type="file" id="uploadedFile" />
38+
</form>
39+
<br>
40+
<button type="button" class="btn btn-success center_buttons" id="encode">&nbsp;&nbsp;Encode&nbsp;&nbsp;</button>
41+
<br>
42+
<button type="button" class="btn btn-danger center_buttons" id="decode">&nbsp;&nbsp;Decode&nbsp;&nbsp;</button>
43+
</div>
44+
</body>
45+
46+
</html>

0 commit comments

Comments
 (0)