-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAdaptiveHuffman.java
More file actions
243 lines (209 loc) · 8.72 KB
/
Copy pathAdaptiveHuffman.java
File metadata and controls
243 lines (209 loc) · 8.72 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
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
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
import java.awt.*;
import java.io.*;
import java.util.*;
import java.util.Scanner;
import java.util.ArrayList;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.text.*;
import javafx.scene.text.Font;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
import javafx.stage.Stage;
import java.io.File;
/**
* Created by menna on 10/23/16.
*/
public class AdaptiveHuffman extends Application {
public static void main(String [] args) {
launch(args);
}
public static File Compress(String path) {
String original = "";
try {
original = new Scanner(new File(path)).useDelimiter("\\Z").next(); // convert everything in file into one string -> content
}
catch (IOException e) {
e.printStackTrace();
}
String result = "";
HashMap<Character, String> Codes = new HashMap<>();
String code = (Integer.toBinaryString(original.getBytes()[0]));
result += code;
Codes.put(original.charAt(0), code); // update codes for nodes
Tree tree = new Tree(100, 0, '!', null, "");
tree.updateTree(original.charAt(0), true); // first occurrence bc first char obviously
for (int i = 1; i < original.length(); i++) { // read symbol
String value = Codes.get(original.charAt(i));
if (value == null) { // first occurrence??
Node nyt = tree.findNYT(); // find NYT
result += nyt.binarycode; // result += nyt code
code = (Integer.toBinaryString(original.getBytes()[i]));
result += code;
tree.updateTree(original.charAt(i), true);
Codes.put(original.charAt(i), code); // add code in hashmap (for later ref - not first occurrence)
}
else { // not first occurrence
String symbol = tree.findNode(original.charAt(i)).binarycode;
result += symbol;
tree.updateTree(original.charAt(i), false);
}
}
File originFile = new File(path);
String dir = originFile.getParent();
File compressed = new File(dir + "\\compressed.txt"); // change to / on linux
try(PrintWriter out = new PrintWriter(dir + "\\compressed.txt")) { // make a new compressed file in same working dir
out.println(result); // write tags
out.close();
}
catch (IOException e) {
e.printStackTrace();
}
return compressed;
//return result;
}
public static File deCompress(String path) {
String code = "";
try {
code = new Scanner(new File(path)).useDelimiter("\\Z").next(); // convert everything in file into one string -> content
}
catch (IOException e) {
e.printStackTrace();
}
String result = "";
String firstCharCode = code.substring(0, 7); // bc 7 bits
// wont work with other non alpha chars bc not 7 bits?
Character firstChar = (char)Byte.parseByte(firstCharCode, 2);
result += firstChar;
Tree tree = new Tree(100, 0, '!', null, "");
tree.updateTree(firstChar, true);
int start = 7; int finish = 8;
String searchFor;
while(finish <= code.length()) {
searchFor = code.substring(start, finish);
Node node = tree.findSymbol(searchFor);
if (node == null || node.symbol == '?') { // found no node continue
finish++;
}
else if (node.symbol == '!') { // NYT
String newCharCode = code.substring(finish, finish + 7);
Character newChar = (char)Byte.parseByte(newCharCode, 2);
result += newChar;
tree.updateTree(newChar, true);
start = finish + 7;
finish = start + 1;
}
else {
result += node.symbol;
tree.updateTree(node.symbol, false);
start = finish; finish++;
}
}
File compressedfile = new File(path);
String dir = compressedfile.getParent();
File decompressed = new File(dir + "\\decompressed.txt");
try(PrintWriter out = new PrintWriter(dir + "\\decompressed.txt")) { // make a decompressed file in same working dir
out.println(result);
out.close();
}
catch (IOException e) {
e.printStackTrace();
}
return decompressed;
//return result;
}
private Desktop desktop = Desktop.getDesktop(); // opening files like this doesnt work on linux
private void openFile(File file) {
try {
desktop.open(file); // use processbuilder for linux
} catch (IOException ex) {
ex.printStackTrace();
}
}
Button browse, compress, decompress;
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Adaptive Huffman Compressor/Decompressor Tool");
Label home = new Label("Choose file to compress/decompress:");
TextField fillWithPath = new TextField();
fillWithPath.setMaxWidth(200);
browse = new Button("Browse");
FileChooser choose = new FileChooser();
browse.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
FileChooser.ExtensionFilter extFilter =
new FileChooser.ExtensionFilter("TEXT files (*.txt)", "*.txt"); // only choose text files
choose.getExtensionFilters().add(extFilter);
// show open file dialog
File file = choose.showOpenDialog(primaryStage);
fillWithPath.setText(file.getAbsolutePath()); // extension filter needed here
}
});
VBox layout1 = new VBox(20);
layout1.setAlignment(Pos.CENTER);
// StackPane layout1 = new StackPane();
compress = new Button("Compress");
decompress = new Button("Decompress");
compress.setOnAction(e -> {
if (fillWithPath.getCharacters().toString().isEmpty()) { // FILE NOT CHOSEN
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("Error");
alert.setHeaderText(null);
alert.setContentText("Please choose a file.");
alert.show();
}
else if (!new File(fillWithPath.getCharacters().toString()).isFile()) {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("Error");
alert.setHeaderText(null);
alert.setContentText("Please choose a valid path");
alert.show();
}
else {
File o = Compress(fillWithPath.getText());
openFile(o);
}
});
decompress.setOnAction(e -> {
if(fillWithPath.getCharacters().toString().isEmpty()) {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("Error");
alert.setHeaderText(null);
alert.setContentText("Please choose a file.");
alert.show();
}
else if (!new File(fillWithPath.getCharacters().toString()).isFile()) {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("Error");
alert.setHeaderText(null);
alert.setContentText("Please choose a valid path");
alert.show();
}
else {
File d = deCompress(fillWithPath.getText());
openFile(d);
}
});
layout1.getChildren().addAll(home, fillWithPath, browse, compress, decompress);
Scene scene = new Scene(layout1, 300, 250);
layout1.setBackground(new Background(new BackgroundFill(Color.LAVENDERBLUSH, CornerRadii.EMPTY, Insets.EMPTY))); //THIS IS SO FUN OMG - LOVE THE COLOR NAMES
compress.setFont(Font.font("Lucida Grande")); // just for fun :) عشان انا فاضية
decompress.setFont(Font.font("Lucida Grande"));
browse.setFont(Font.font("Lucida Grande"));
fillWithPath.setFont(Font.font("Lucida Grande"));
home.setFont(Font.font("Lucida Grande"));
primaryStage.setScene(scene);
primaryStage.show();
}
}