//package util;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class FileCompressor {
private Map countMap;
private List topWords;
private Map map;
private static final char[] WORDS =
{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
public String compress(String context) {
context = context.toLowerCase();
preprocess(context);
StringBuilder mapLine = new StringBuilder();
for (Entry e : map.entrySet()) {
String key = e.getKey();
String value = e.getValue().toString();
context = context.replace(key, value);
mapLine.append(key);
mapLine.append(value);
}
mapLine.append(System.getProperty("line.separator"));
StringBuilder out = new StringBuilder(context);
out.insert(0, mapLine.toString());
map = null;
return out.toString();
}
public String decompress(String context) throws IOException {
// process map line
BufferedReader reader = new BufferedReader(new StringReader(context));
String mapLine = reader.readLine();
mapLineprocess(mapLine);
// create content without mapline
StringBuilder out = new StringBuilder();
String tmp;
while ((tmp = reader.readLine()) != null) {
out.append(tmp);
out.append(System.getProperty("line.separator"));
}
context = out.toString();
for (Entry e : map.entrySet()) {
String key = e.getKey();
String value = e.getValue().toString();
context = context.replace(value, key);
}
return context;
}
private void mapLineprocess(String mapLine) {
// create map for character replacement
if (map == null) {
map = new HashMap();
}
char[] line = mapLine.toCharArray();
StringBuilder key = new StringBuilder();
for (int i = 0; i < line.length; i += 3) {
key.append(line[i]);
key.append(line[i + 1]);
map.put(key.toString(), line[i + 2]);
key.setLength(0);
}
}
private void preprocess(String content) {
// count and get top used words
count(content);
// create map for character replacement
if (map == null) {
map = new HashMap();
}
for (int i = 0; i < WORDS.length && i < topWords.size(); i++) {
map.put(topWords.get(i), WORDS[i]);
}
topWords = null;
}
private boolean isBreakLine(char ch) {
char[] breakLine = System.getProperty("line.separator").toCharArray();
for (char c : breakLine) {
if (c == ch)
return true;
}
return false;
}
private void count(String content) {
if (countMap == null) {
countMap = new HashMap();
}
char[] chs = content.toCharArray();
StringBuilder bytestr = new StringBuilder();
// count
for (char ch : chs) {
if (isBreakLine(ch))
continue;
bytestr.append(ch);
if (bytestr.length() == 2) {
int count = 0;
if (countMap.containsKey(bytestr.toString())) {
count = countMap.get(bytestr.toString());
}
countMap.put(bytestr.toString(), ++count);
bytestr.setLength(0);
}
}
// sort
List> lists = new ArrayList>();
lists.addAll(countMap.entrySet());
Collections.sort(lists, new Comparator>() {
@Override
public int compare(Entry pO1, Entry pO2) {
return pO2.getValue().compareTo(pO1.getValue());
}
});
// to top words
if (topWords == null) {
topWords = new ArrayList();
}
for (int i = 0; i < WORDS.length && i < lists.size(); i++) {
topWords.add(i, lists.get(i).getKey());
}
countMap = null;
}
public static void main(String[] args) throws IOException {
String file = "D:\\XJad.rar.txt";
BufferedReader reader = new BufferedReader(new FileReader(file));
BufferedWriter writer = new BufferedWriter(new FileWriter(file + "_out.txt"));
StringBuilder content = new StringBuilder();
String tmp;
while ((tmp = reader.readLine()) != null) {
content.append(tmp);
content.append(System.getProperty("line.separator"));
}
FileCompressor f = new FileCompressor();
writer.write(f.compress(content.toString()));
writer.close();
reader.close();
reader = new BufferedReader(new FileReader(file + "_out.txt"));
StringBuilder content2 = new StringBuilder();
while ((tmp = reader.readLine()) != null) {
content2.append(tmp);
content2.append(System.getProperty("line.separator"));
}
String decompressed = f.decompress(content2.toString());
String c = content.toString();
System.out.println(decompressed.equals(c));
}
}