文章目录
- 前言
- 一、需求分析
- 课程设计题目:
- 二、概要设计
- 1.核心算法模块:
- 2.文件读写模块:
- 3.界面显示模块:
- 三、详细设计
- 1.核心算法模块:
- 2.文件读写模块
- 3.界面显示模块:
- 四、代码
一、需求分析
课程设计题目:
设计一个哈夫曼编码/译码系统,对一个文本文件中的字符进行哈曼编码,生成编码文件(压缩文件,后缀名.cod);反过来,可将一个压缩文件译码还原为文本文件(.txt).
1.核心算法模块: 使用哈夫曼编码算法对给定的文本文件进行压缩/解压处理,要求可靠性强且效率高。
2.文件读写模块: 使用Java字节流的方式读写对应的文本文件,要求效率较高,且有较强的鲁棒性。
3.界面显示模块: 使用Java Swing类库来完成解压缩操作的可视化,界面要求简洁大方,易于使用,具有较强的交互性。
二、概要设计
1.核心算法模块:
算法关键存储结构说明:
(1).哈夫曼树: 每一个叶子结点存储对应字符作为数据域,相应出现的次数作为权重. (2)StringBuilder: 用于拼接字符串.
(3)byte[]数组: 存储压缩生成的二进制编码(如010110). (4)Map<Byte,String>: 存储二进制数及其权重
(5)ArrayList: 对(4)中的Map再封装 (6)ObjectInputStream:
对象输出流,用于一次性将对象数据写入文件 (7) ObjectOutputStream: 对象输出流,一次性将对象读取入内存
2.文件读写模块:
通过Java IO流操作进行读写文件, 由于有处理中文的需求,这里选择了字节流读写文本, 防止字符流在操作压缩文件的时候出现不必要的乱码问题.
3.界面显示模块:
鉴于控制台操作的程序交互性较差,这里使用了Java的Swing类库, 能让用户自己选择文件进行解压缩, 解压之后的程序信息显示,读取解压文本,并自动打开文件所在的位置.
三、详细设计
1.核心算法模块:
(1). zip(byte[] bytes,Map<Byte,String>huffmanCodes)
本程序的核心压缩算法, 由于需要压缩成一个二进制变量,参数一 bytes是从文本文件中读取来的二进制的数组, 而huffmanCodes则是我们根据哈夫曼树得到的键值对结构.
在算法中,我们的最终目的是得到一个二进制变量,根据计算机中原码,反码,补码的知识我们得到, 对于大于8位的字符,如果其总长度对8取模运算,很有可能结果不是0(即总长不是8的倍数),对于这种情况,我们需要对其补0,将其补位8位的二进制数.
最后,用Integer方法的parseInt(String,radix)将得到的字符串按每8位拆解的方式转换为二进制数,最后通过文本操作存入cod文件,同时也要存入哈夫曼编码表,否则在解压的时候就会匹配失败.
(2).unZip(Map<Byte,String>huffmanCodes,byte[]huffmanBytes)
本程序的核心解压算法,需要一个辅助的Map将键值对转置,即将读取到的二进制数按每8位与之前生成的哈夫曼编码表进行匹配,匹配到了就保存文本,没匹配到就继续循环,直到匹配成功.
(3). binaryToStr(byte b)
将传入的byte进行 |=0x100运算,即如果传入是正数,就补高位,反之运算不生效. 然后通过Integer.toBinaryString()方法将将byte类型的数据转为字符串并返回
(4). 计算压缩率:
压缩率=(压缩前字节长度-压缩后字节长度)/ 压缩前字节长度
使用NumberFormat类将数值类型的压缩率转换为字符串并返回显示到界面中.
(5). 关于二次封装操作的说明: 二次封装的面向对象开发中的常用手段,Java语言的关键字和类名普遍较长, 而很多时候形参列表是不能缩减的,这就造成了可读性的下降.方法中大量的变量定义,函数调用也让代码非常的不优雅, 因此对zip(byte[] bytes,Map<Byte,String>huffmanCodes)方法做了二次封装.
2.文件读写模块
(1).compass(StringfromPath,String toPath)deCompass(String fromPath,String toPath):
ObjectInputStream, ObjectOutputStream(对象输入流与对象输出流).
这两个类的readObject()和writeObject()方法能将对象数据一次性写入到文件中.
3.界面显示模块:
Java的swing插件开发中,方法间区分不明显,下面分功能讲解
(1).三个按钮间的逻辑: 在这里,我们将三个按钮分别命名压缩,解压,保存. 页面初始化后,三个按钮都是可点击的,当我们点击压缩按钮时,解压按钮会随之禁用,当选中保存地址时, 压缩操作开始,文件自动压缩,完成后自动打开压缩文件所在的文件夹. 解压操作同理.
(2). 提示信息: 在提示信息处,会打印操作执行的时间,文件存储的地址.
(3). 文本显示: 将解压完成后的文本打印的在文本域中.
四、代码
核心算法:
package edu.cust.cs.bean;
import java.io.*;
import java.text.NumberFormat;
import java.util.*;
public class HuffmanCode {
static StringBuilder stringBuilder = new StringBuilder();
public static Map<Byte, String> huffmanCode = new HashMap<Byte, String>();
public static void main(String[] args) {
}
public static String getText(String path) {
ArrayList<String> list = new ArrayList<String>();
StringBuilder stringBuilder = new StringBuilder();
String text = "";
try {
File file = new File(path);// 创建文件对象file
FileReader fileReader = new FileReader(file); // fr对象 对应f的读出
BufferedReader br = new BufferedReader(fileReader);// br是 对应fr的 读出缓冲区
String out = null;
int i = 0;
while ((out = br.readLine()) != null) {
list.add(out);// 用一个数组全部存起来方便修改
System.out.println(out);
}
for (int j = 0; j < list.size(); j++)
// stringBuilder.append(list.get(j));
text+=(list.get(j)+"\n");
br.close();
} catch (Exception ex) {
ex.printStackTrace();
}
// return new String(stringBuilder);
return text;
}
public static String compass(String fromPath, String toPath) {
// 创建输出流
OutputStream outputStream = null;
ObjectOutputStream objectOutputStream = null;
// 创建文件的输入流
FileInputStream inputStream = null;
String zipRate = null;
try {
inputStream = new FileInputStream(fromPath);
byte[] b = new byte[inputStream.available()];
inputStream.read(b); // 读取文件内容到二进制数组
byte[] huffmanBytes = zip(b); // 压缩成字节数组变量
outputStream = new FileOutputStream(toPath);
objectOutputStream = new ObjectOutputStream(outputStream);
// 向文件中写入哈夫曼编码和二进制数组
objectOutputStream.writeObject(huffmanBytes);
objectOutputStream.writeObject(huffmanCode);
// 计算压缩率 , 公式: rate = (压缩前的字节数组长度 - 压缩后) / 压缩前
NumberFormat numberFormat = NumberFormat.getInstance(); // 转换为字符串
numberFormat.setMinimumFractionDigits(1); // 小数点后保留2位
zipRate = numberFormat.format(100 * ((float) (b.length - huffmanBytes.length) / (float) b.length));
System.out.println(zipRate + "%"); // 输出压缩率
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
} finally {
try {
// 关闭流
inputStream.close();
objectOutputStream.close();
outputStream.close();
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
}
return (zipRate + "%");
}
public static void deCompass(String fromPath, String toPath) {
InputStream inputStream = null;
ObjectInputStream oInputStream = null; // 使用对象输入流,将数据对象一次性写入到文件里
OutputStream outputStream = null;
try {
// 创建文件输入流
inputStream = new FileInputStream(fromPath);
// 创建一个和 is关联的对象输入流
oInputStream = new ObjectInputStream(inputStream);
// 读取byte数组 huffmanBytes
byte[] huffmanBytes = (byte[]) oInputStream.readObject();
// byte[] huffmanBytes =(byte[]) inputStream.read();
// 读取赫夫曼编码表
Map<Byte, String> huffmanCodes = (Map<Byte, String>) oInputStream.readObject();
// 解码
byte[] bytes = unZip(huffmanCodes, huffmanBytes);
outputStream = new FileOutputStream(toPath);
outputStream.write(bytes);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
} finally {
try {
outputStream.close();
oInputStream.close();
inputStream.close();
} catch (Exception e2) {
// TODO: handle exception
System.out.println(e2.getMessage());
}
}
}
// public String getZipRate() {
//
// byte[] strBytes = str.getBytes();
// NumberFormat numberFormat = NumberFormat.getInstance();
// numberFormat.setMinimumFractionDigits(2); //小数点后保留3位
//
System.out.println("压缩结果如下");
// byte[] zip = huffmanZip(strBytes);
// System.out.println(Arrays.toString(zip));
// String zipRate = numberFormat.format(100 * ((float)(strBytes.length - zip.length) / (float) strBytes.length));
// System.out.println(zipRate+"%"); //输出压缩率
// return (zipRate+"%");
// }
/**
* 解压算法
*
* @param huffmanCodes 编码表(各个字符对于的二进制数)
* @param huffmanBytes //压缩后的二进制数
* @return
*/
public static byte[] unZip(Map<Byte, String> huffmanCodes, byte[] huffmanBytes) {
Map<String, Byte> map = new HashMap<String, Byte>();
StringBuilder stringBuilder = new StringBuilder();
List<Byte> arr = new ArrayList<>();
for (int i = 0; i < huffmanBytes.length - 1; i++) { // 对二进制计算
byte b = huffmanBytes[i];
String str = binaryToStr(b); // str是二进制字符串
boolean isFinal = (i == huffmanBytes.length - 2); // 判断是否数组中余下的数字(%8 剩下的位数就是)
if (isFinal) {
byte by = huffmanBytes[huffmanBytes.length - 1];
str = str.substring(0, by);
}
stringBuilder.append(str); // 拼接字符串
}
for (Map.Entry<Byte, String> entry : huffmanCodes.entrySet()) {
map.put(entry.getValue(), entry.getKey()); // 键值对转置
}
for (int i = 0; i < stringBuilder.length();) {
int count = 1;
boolean flag = true;
Byte by = null;
while (flag) {
String key = stringBuilder.substring(i, i + count);
by = map.get(key);
if (by == null) { // 没匹配到完整的字符
count++;
} else {
// 找到了
flag = false;
}
}
arr.add(by);
i += count;
}
byte[] b = new byte[arr.size()];
for (int i = 0; i < b.length; i++) { // 取出二进制数组并返回
b[i] = arr.get(i);
}
return b;
}
private static String binaryToStr(byte b) {
// 使用临时变量保存 b
int tmp = b;
tmp |= 0x100; // byte对256进行|操作,正数补高位
String str = Integer.toBinaryString(tmp); // 包装类方法,将int转为2进制的字符串
return str.substring(str.length() - 8); //
}
private static Node createHuffmanTree(List<Node> nodes) {
while (nodes.size() > 1) {
Collections.sort(nodes);
Node leftNode = nodes.get(0);
Node rightNode = nodes.get(1);
Node parent = new Node(null, leftNode.weight + rightNode.weight);
parent.left = leftNode;
parent.right = rightNode;
nodes.remove(leftNode);
nodes.remove(rightNode);
nodes.add(parent);
}
return nodes.get(0);
}
// 二次封装zip方法
public static byte[] zip(byte[] bytes) {
List<Node> nodes = getNodes(bytes);
Node huffmanTreeRoot = createHuffmanTree(nodes);
Map<Byte, String> huffmanCodes = getCodes(huffmanTreeRoot);
byte[] huffmanMapByte = zip(bytes, huffmanCodes);
return huffmanMapByte;
}
//
private static byte[] zip(byte[] bytes, Map<Byte, String> huffmanCodes) { // 压缩
int length;
StringBuilder stringBuilder = new StringBuilder();
for (byte b : bytes) {
stringBuilder.append(huffmanCodes.get(b));
}
// 统计返回 byte[] huffmanCodeBytes 长度
byte count = (byte) (stringBuilder.length() % 8);
if (count == 0) {
length = stringBuilder.length() / 8;
} else {
length = stringBuilder.length() / 8 + 1;
// 后面补零
for (int i = count; i < 8; i++) {
stringBuilder.append('0'); // 补成8位二进制
}
}
byte[] huffmanCodeBytes = new byte[length + 1];
// byte[] huffmanCodeBytes = new byte[length];
huffmanCodeBytes[length] = count;
int index = 0;// 记录是第几个byte
for (int i = 0; i < stringBuilder.length(); i += 8) {
String strByte;
strByte = stringBuilder.substring(i, i + 8);
// 将strByte 转成一个byte,放入到 huffmanCodeBytes
huffmanCodeBytes[index] = (byte) Integer.parseInt(strByte, 2);
index++;
}
return huffmanCodeBytes;
}
private static Map<Byte, String> getCodes(Node root) {
if (root == null) {
return null;
}
// 处理root的左子树
getCodes(root.left, "0", new StringBuilder());
// 处理root的右子树
getCodes(root.right, "1", new StringBuilder());
return huffmanCode;
}
// 获取结点的权重
private static List<Node> getNodes(byte[] bytes) {
ArrayList<Node> nodes = new ArrayList<Node>();
Map<Byte, Integer> counts = new HashMap<Byte, Integer>();
for (byte b : bytes) {
Integer count = counts.get(b);
if (count == null) { // 第一次出现
counts.put(b, 1);
} else {
counts.put(b, count + 1);
}
}
for (Map.Entry<Byte, Integer> entry : counts.entrySet()) {
nodes.add(new Node(entry.getKey(), entry.getValue()));
}
return nodes;
}
public static void getCodes(Node node, String code, StringBuilder stringBuilder) {
StringBuilder stringBuilder1 = new StringBuilder(stringBuilder);
stringBuilder1.append(code); // 拼接code
if (node != null) {
if (node.data == null) { // 非叶子结点,就继续递归调用
getCodes(node.left, "0", stringBuilder1);
getCodes(node.right, "1", stringBuilder1);
} else { // 叶子结点
huffmanCode.put(node.data, stringBuilder1.toString()); // 以键值对方式加入编码表
}
}
}
// 获取哈夫曼编码表
public static Map<Byte, String> getHuffmanCodes(byte[] bytes) {
List<Node> nodes = HuffmanCode.getNodes(bytes);
Node root = HuffmanCode.createHuffmanTree(nodes);
huffmanCode = HuffmanCode.getCodes(root);
return huffmanCode;
}
}
class Node implements Comparable<Node> {
Byte data; // 数据域
Integer weight; // 权重
Node left;
Node right;
public Node(Byte data, Integer weight) {
this.data = data;
this.weight = weight;
}
@Override
public String toString() {
return "bean.Node{" + "data=" + data + ", weight=" + weight + '}';
}
@Override
public int compareTo(Node o) {
return this.weight - o.weight;
}
public void preOrder() { // 前序遍历
System.out.println(this);
if (this.left != null) {
this.left.preOrder();
}
if (this.right != null) {
this.right.preOrder();
}
}
}
//封装
package edu.cust.cs.service;
import edu.cust.cs.bean.HuffmanCode;
public class FileService {
public static void main(String[] args) {
}
//压缩文件
public static String compress(String fromPath,String toPath) {
try {
String rate = HuffmanCode.compass(fromPath, toPath);
return rate;
}catch(Exception e) {
e.printStackTrace();
return "fail";
}
}
//解压文件
public static String deCompress(String fromPath,String toPath) {
try {
HuffmanCode.deCompass(fromPath, toPath);
return "解压成功";
}catch(Exception e) {
e.printStackTrace();
return "fail";
}
}
}
界面:
package edu.cust.cs.view;
import java.awt.BorderLayout;
import java.awt.Desktop;
import java.awt.EventQueue;
import java.awt.Font;
import javax.swing.JFrame;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
import javax.swing.filechooser.FileNameExtensionFilter;
import edu.cust.cs.bean.HuffmanCode;
import edu.cust.cs.service.FileService;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class XiaoZip {
private JFrame frame;
String frompath;
String toPath;
boolean isZip = true; //默认为压缩
String saveAsName; //保存的路径
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
XiaoZip window = new XiaoZip();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public XiaoZip() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 900, 750);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
JButton btnNewButton = new JButton("\u538B\u7F29");
JButton btnNewButton_1 = new JButton("\u9009\u4E2D\u5B58\u653E\u76EE\u5F55");
btnNewButton_1.setEnabled(false);
JButton btnNewButton_2 = new JButton("\u89E3\u538B");
JTextArea textArea = new JTextArea();
textArea.setBounds(14, 13, 427, 524);
JTextArea textArea_1 = new JTextArea();
textArea_1.setBounds(661, 323, 207, 337);
frame.getContentPane().add(textArea_1);
btnNewButton_2.addMouseListener(new MouseAdapter() { //解压
@Override
public void mouseClicked(MouseEvent e) {
btnNewButton.setEnabled(false); //禁用压缩按钮
JFileChooser chooser = new JFileChooser(); // 设置选择器
FileNameExtensionFilter filter = new FileNameExtensionFilter("压缩包文件(.cod)", "cod");
chooser.setMultiSelectionEnabled(true); // 设为多选
chooser.setFileFilter(filter);
int returnVal = chooser.showOpenDialog(btnNewButton_2); // 是否打开文件选择框
System.out.println("returnVal=" + returnVal);
if (returnVal == JFileChooser.APPROVE_OPTION) { // 如果符合文件类型
System.out.println("~选择上传文件位置");
frompath = chooser.getSelectedFile().getAbsolutePath(); // 获取绝对路径
// FileUtils.compress(frompath, toPath);
if(!frompath.contains("cod")) {
JOptionPane.showMessageDialog(null, "文件类型错误", "提示", JOptionPane.ERROR_MESSAGE);
}
System.out.println("选择的文件路径为 "+frompath);
System.out.println("You chose to open this file: " + chooser.getSelectedFile().getName()); // 输出相对路径
JOptionPane.showMessageDialog(null, "请选择解压文件保存路径 ", "提示", JOptionPane.INFORMATION_MESSAGE);
btnNewButton_1.setEnabled(true); //取消禁用
String tmp = chooser.getSelectedFile().getName().trim();
String[] strs = tmp.split("\\.");
saveAsName = strs[0];
isZip = false; //解压
System.out.println(saveAsName); //显示文件名
}
}
});
btnNewButton_2.setBounds(675, 103, 147, 27);
btnNewButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
btnNewButton_2.setEnabled(false); //禁用解压按钮
JFileChooser chooser = new JFileChooser(); // 设置选择器
FileNameExtensionFilter filter = new FileNameExtensionFilter("文本文件", "txt");
chooser.setMultiSelectionEnabled(true); // 设为多选
chooser.setFileFilter(filter);
int returnVal = chooser.showOpenDialog(btnNewButton); // 是否打开文件选择框
System.out.println("returnVal=" + returnVal);
//设置为接收txt文件
if (returnVal == JFileChooser.APPROVE_OPTION) { // 如果符合文件类型
System.out.println("~选择上传文件位置");
frompath = chooser.getSelectedFile().getAbsolutePath(); // 获取绝对路径
System.out.println("选择的文件路径为 "+frompath);
System.out.println("You chose to open this file: " + chooser.getSelectedFile().getName()); // 输出相对路径
JOptionPane.showMessageDialog(null, "请选择压缩文件保存路径 ", "提示", JOptionPane.INFORMATION_MESSAGE);
btnNewButton_1.setEnabled(true); //取消禁用
String tmp = chooser.getSelectedFile().getName().trim();
String[] strs = tmp.split("\\."); //不加\\无法截取
saveAsName = strs[0];
System.out.println(saveAsName);
}
}
});
btnNewButton_1.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
// 按钮点击事件
System.out.println("~选择压缩文件位置");
JFileChooser chooser = new JFileChooser(); // 设置选择器
// chooser.setMultiSelectionEnabled(true); // 设为多选
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int returnVal = chooser.showOpenDialog(btnNewButton_1); // 是否打开文件选择框
System.out.println("returnVal=" + returnVal);
if (returnVal == JFileChooser.APPROVE_OPTION) { // 如果符合文件类型
if(chooser.getSelectedFile().isDirectory()) {
//选择的是文件夹就保存
toPath = chooser.getSelectedFile().getAbsolutePath();
String tmp = toPath;
if(isZip) {
toPath += ("/"+saveAsName)+".cod";
System.out.println(toPath);
//压缩率
String rate = FileService.compress(frompath, toPath);
textArea_1.setFont(new Font("黑体",Font.BOLD,16));
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
textArea_1.append(df.format(new Date())+"\n");
textArea_1.append("压缩率 "+rate);
textArea_1.append("\n文件存放地址为 "+toPath);
try {
Desktop.getDesktop().open(new File(tmp)); //打开所在目录
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
btnNewButton_2.setEnabled(true);
} else {
textArea.setEnabled(true);
textArea.setText(" ");
toPath += ("/"+saveAsName)+".txt";
System.out.println(toPath);
FileService.deCompress(frompath, toPath);
//获取当前时间
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
// System.out.println(df.format(new Date()));// new Date()为获取当前系统时间
textArea_1.setFont(new Font("黑体",Font.BOLD,16));
textArea_1.append(("\n"+df.format(new Date())+"\n"));
textArea_1.append("解压完成,请查收文件");
textArea_1.append("\n"+"文件存放地址为 "+toPath);
textArea.setText( HuffmanCode.getText(toPath));
textArea.setEnabled(false);
btnNewButton_2.setEnabled(true);;
try {
Desktop.getDesktop().open(new File(tmp)); //打开所在目录
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
btnNewButton_1.setEnabled(true);
}
}
}
}
});
btnNewButton_1.setBounds(675, 166, 147, 27);
btnNewButton.setBounds(675, 30, 147, 27);
frame.getContentPane().add(btnNewButton);
frame.getContentPane().add(btnNewButton_1);
JLabel lblNewLabel = new JLabel("\u63A7\u5236\u53F0");
lblNewLabel.setBounds(727, 323, 72, 18);
frame.getContentPane().add(lblNewLabel);
// frame.getContentPane().add(textArea);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setBounds(13, 10, 634, 650);
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
JScrollPane scrollPane_1 = new JScrollPane(textArea_1);
scrollPane_1.setBounds(661, 354, 207, 306);
scrollPane_1.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollPane_1.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
frame.getContentPane().add(scrollPane, BorderLayout.PAGE_START);
frame.getContentPane().add(scrollPane_1, BorderLayout.PAGE_END);
frame.getContentPane().add(btnNewButton_2);
}
}