package homework6;


import java.awt.Color;

import java.awt.Dimension;

import java.awt.Font;

import java.awt.GridLayout;

import java.awt.Image;

import java.awt.Toolkit;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.PrintStream;

import java.net.MalformedURLException;

import java.util.BitSet;

import java.util.Comparator;

import java.util.HashMap;

import java.util.Map;

import java.util.Map.Entry;

import java.util.PriorityQueue;

import java.util.Queue;

import java.util.Scanner;


import javax.swing.ImageIcon;

import javax.swing.JButton;

import javax.swing.JFileChooser;

import javax.swing.JFrame;

import javax.swing.filechooser.FileNameExtensionFilter;


import homework.huffman;



public class Huffman {

private static class HuffmanComparator implements Comparator{

public int compare(HNODE node1,HNODE node2) {

return node1.freq - node2.freq;

}

}

public Huffman() {};

//파일의 존재유무 및 변환가능 파일인지 확인 후 메세지요청

public static void compresss(String input) throws FileNotFoundException, IOException{

if(input == null) {

throw new NullPointerException("파일을 넣지 않았습니다.");

}

if(input.length()==0) {

throw new IllegalArgumentException("UTF-16으로 인코딩할 수 없습니다.");

}

String Put_Path = null;

String File_name = null;

JFileChooser chooser = new JFileChooser();

FileNameExtensionFilter filter = new FileNameExtensionFilter("cmp",".cmp","CMP");

chooser.setFileFilter(filter);

int retrival = chooser.showSaveDialog(null);

if(retrival == JFileChooser.APPROVE_OPTION) {

System.out.println(chooser.getCurrentDirectory().toString());

Put_Path =chooser.getCurrentDirectory().toString();

File_name = chooser.getSelectedFile().getName();

System.out.println(File_name);

}else {

System.out.println("파일을 찾을 수 없습니다.");

}

}

final Map charFreq = getCharFrequency(input);

final HNODE root = buildTree(charFreq);

final Map charCode = CodeGenerator(charFreq.keySet(),root);

final String encoded_input = encodeInput(charCode,input);

//숫자와 글자를 연산처리하는 곳.

private static Map getCharFrequency(String input){

final Map map = new HashMap();

for(int i=0;i<input.length();i++) {

char ch = input.charAt(i);

if(map.containsKey(ch)) {

int val = map.get(ch);

map.put(ch,++val);

}

else {

map.put(ch, 1);

}

}

return map;

}

private static HNODE buildTree(Mapmap) {

final Queue Priority_Queue = createPrioQueue(map);

while(Priority_Queue.size()>1) {

final HNODE node1 = Priority_Queue.remove();

final HNODE node2 = Priority_Queue.remove();

HNODE node = new HNODE('\0',node1.freq +node2.freq,node1,node2);

Priority_Queue.add(node);

}

return Priority_Queue.remove();

}

//HNODE를 처음으로 돌리는 곳.

private static Queue createPrioQueue(Map map){

final Queue P_Q = new PriorityQueue(10, new HuffmanComparator());

for(Entry entry : map.entrySet()){

P_Q.add(new HNODE(entry.getKey(),entry.getValue(),null,null));

}

return P_Q;

}

//문자를 허프만 코드로 변경하는 부분

private static void Generator(HNODE node,Map map,String s) {

if(node.left == null && node.right == null) {

map.put(node.ch, s);

return;

}

//각 글자를 0과 1로 변환함

Generator(node.left, map, s+'0');

Generator(node.right, map, s+'1');

}

//인코딩할 때 맵의 값을 불러오는 부분

private static String encodeInput(Map charCode,String input) {

final StringBuilder S_B = new StringBuilder();

for(int i=0;i<input.length();i++) {

S_B.append(charCode.get(input.charAt(i)));

}

return S_B.toString();

}

private static void serializeTree(HNODE node,String Put_Path,String File_name) throws FileNotFoundException,IOException{

final BitSet bitset = new BitSet();

try(ObjectOutputStream oops_Tree = new ObjectOutputStream(new FileOutputStream(Put_Path+"/"+"tree")))

{

try(ObjectOutputStream oops_Char = new ObjectOutputStream(new FileOutputStream(Put_Path+"/"+"char")))

{

IntObject o = new IntObject();

preOrder(node,oops_Char,bitset,o);

bitset.set(o.bitPosition,true);

oops_Tree.writeObject(bitset);

}

}

}

private static class IntObject{

int bitPosition;

}

//

private static void preOrder(HNODE node,ObjectOutputStream oopsChar,BitSet bitset,IntObject intobject) throws IOException{

if(node.left == null&&node.right == null) {

bitset.set(intobject.bitPosition++,false);

oopsChar.writeChar(node.ch);

return;

}

bitset.set(intobject.bitPosition++,true);

preOrder(node.left, oopsChar, bitset, intobject);

bitset.set(intobject.bitPosition++, true);              

    preOrder(node.right, oopsChar, bitset, intobject);

}

private static void serializeInput(String message,String Put_path,String File_name) throws IOException {

    final BitSet bitset = getBitSet(message);

    try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(Put_path+"/" + File_name+".cmp"))){

        oos.writeObject(bitset);

    } 

}

private static BitSet getBitSet(String message){

final BitSet bitset = new BitSet();

int i=0;

for(i=0;i

{

if(message.charAt(i)=='1')

{

bitset.set(i,true);

}

else

{

bitset.set(i,false);

}

}

//this will show the end

bitset.set(i,true);

return bitset;

}

private static void expand(String File_dir,String File_name)throws FileNotFoundException,ClassNotFoundException,IOException{

final HNODE root = deserializeTree(File_dir);

decodeMessage(root, File_dir+"/"+File_name);

}

private static HNODE deserializeTree(String File_url) throws FileNotFoundException, IOException, ClassNotFoundException {

    try (ObjectInputStream oisBranch = new ObjectInputStream(new FileInputStream(File_url+"/"+"tree"))) {

        try (ObjectInputStream oisChar = new ObjectInputStream(new FileInputStream(File_url+"/"+"char"))) {

            final BitSet bitSet = (BitSet) oisBranch.readObject();

            return preOrder(bitSet, oisChar, new IntObject());

        }

    }

}

private static HNODE preOrder(BitSet bitSet, ObjectInputStream osChar, IntObject o)throws IOException{

final HNODE node = new HNODE('\0', 0, null, null);

if(!bitSet.get(o.bitPosition)) {

o.bitPosition++;

node.ch = osChar.readChar();

return node;

}

o.bitPosition = o.bitPosition+1;

node.left = preOrder(bitSet, osChar, o);

o.bitPosition = o.bitPosition+1;

node.right = preOrder(bitSet, osChar, o);

return node;

}

private static void decodeMessage(HNODE node, String File_url) throws FileNotFoundException, IOException, ClassNotFoundException{

try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream(File_url))){

final BitSet bitSet = (BitSet) ois.readObject();

final StringBuilder stringBuilder = new StringBuilder();

for(int i=0;i<(bitSet.length()-1);) {

HNODE temp = node;

while(temp.left != null) {

if(!bitSet.get(i)) {

temp = temp.left;

}

else {

temp = temp.right;

}

i = i+1;

}

stringBuilder.append(temp.ch);

}

String Put_Path = null;

String File_name = null;

JFileChooser chooser = new JFileChooser();

FileNameExtensionFilter filter = new FileNameExtensionFilter("TEXT FILES","txt","text");

chooser.setFileFilter(filter);

int retrival = chooser.showSaveDialog(null);

if(retrival == JFileChooser.APPROVE_OPTION) {

System.out.println(chooser.getCurrentDirectory().toString());

Put_Path = chooser.getCurrentDirectory().toString();

System.out.println(File_name);

}

else {

System.out.println("파일이 선택되지 않았습니다.");

}

try(PrintStream out = new PrintStream(new FileOutputStream(Put_Path+"/"+File_name+".txt"))){

out.print(stringBuilder.toString());

}

}

}

public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException,MalformedURLException {

Image image = new ImageIcon("res/zip.png").getImage();

Font font1 = new Font("Arial", Font.PLAIN, 25);

JFrame frame = new JFrame ("허프만 Zip");

frame.setSize(800, 250);

Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();

frame.setLocation(dim.width/2-frame.getSize().width/2, dim.height/2-frame.getSize().height/2);

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.getContentPane().setLayout(new GridLayout(2,1));

JButton compress_btn = null;

JButton decompress_btn = null;

compress_btn = new JButton("파일압축");

compress_btn.setBackground(Color.GREEN);

compress_btn.setFont(font1);

decompress_btn = new JButton("파일압축해제");

decompress_btn.setBackground(Color.GRAY);

decompress_btn.setFont(font1);

frame.add(compress_btn);

frame.add(decompress_btn);

frame.setIconImage(image);

frame.setVisible(true);

compress_btn.addActionListener(new ActionListener() {

@Override

public void actionPerformed(ActionEvent arg0) {

// TODO Auto-generated method stub

//browse file to compress

JFileChooser chooser = new JFileChooser();

FileNameExtensionFilter filter = new FileNameExtensionFilter("TEXT FILES", "txt", "text");

chooser.setFileFilter(filter);

    chooser.setCurrentDirectory(new java.io.File("."));

    chooser.setDialogTitle("파일선택하기");

    chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);     

    chooser.setAcceptAllFileFilterUsed(false);

    File phile = null;

    

    if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {

    phile = chooser.getSelectedFile();

    } else {

        System.out.println("파일이 선택되지 않았습니다.");

    }


String content = null;

try {

content = new Scanner(phile).useDelimiter("\\Z").next();

} catch (FileNotFoundException e) {

e.printStackTrace();

}

try {

huffman.compress(content);

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

});

decompress_btn.addActionListener(new ActionListener() {

@Override

public void actionPerformed(ActionEvent arg0) {

JFileChooser chooser = new JFileChooser();

FileNameExtensionFilter filter = new FileNameExtensionFilter("cmp",".cmp","CMP");

chooser.setFileFilter(filter);

    chooser.setCurrentDirectory(new java.io.File("."));

    chooser.setDialogTitle("압축을 해제하였습니다.");

    chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);     

    chooser.setAcceptAllFileFilterUsed(false);

    File phile = null;

    

    if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {

    System.out.println(chooser.getCurrentDirectory());

    phile = chooser.getSelectedFile();

    } else {

        System.out.println("파일이 선택되지 않았습니다.");

    }

try {

huffman.expand(chooser.getCurrentDirectory().toString(),phile.getName());

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

});

}

}


기본적으로 이정도는 짜자 애들아.