1. 声明
当前内容主要为使用Swing来实现一个文件压缩器,借助Apache Commons来实现,内容借鉴:官方文档
主要涉及以下Swing组件
- JTable中自定义CellRenderer,CellEditor,隐藏列
- JProgressorBar的使用
- JDialog的使用
- 实现拖拽文件到table中
基本pom依赖
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.20</version>
</dependency>
<dependency>
<groupId>org.tukaani</groupId>
<artifactId>xz</artifactId>
<version>1.9</version>
</dependency>
2. 界面展示
这里压缩后的文件是可以使用rar进行解压的
3. 压缩的实体的解释
对于压缩文件:aaa/aaa.txt,其中aaa就表示一个文件夹,aaa.txt就是该文件夹中的文件,但是在压缩的时候是只有一个实体名称aaa/aaa.txt,使用的却是aaa文件夹和aaa.txt文件,所以对于这个需要特殊的处理操作!
所以对于压缩文件来讲,只需要考虑文件的名称即可(文件夹在解压时会自动创建)
对于文件aaa.txt是放在根目录,那么只需要使用aaa.txt作为实体名称即可
4. 代码
1. 主程序:
package com.hy.test;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.event.CellEditorListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import com.hy.test.progressbar.SimpleProgressBarPanel;
import com.hy.test.progressbar.SimpleTask;
import com.hy.test.zip.compress.CompressCallback;
import com.hy.test.zip.compress.ZipCompressor;
import com.hy.test.zip.compress.impl.GzipCompressor;
import com.hy.test.zip.compress.impl.SevenZCompressor;
import com.hy.test.zip.compress.impl.ZipCompressorImpl;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.Dimension;
import javax.swing.JRadioButton;
import java.awt.Font;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.EventObject;
import java.util.List;
import java.util.Vector;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.JPopupMenu;
import java.awt.event.MouseAdapter;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
/**
*
* @author hy
* @createTime 2022-10-09 12:44:50
* @description 用于实现压缩文件(目标,将多个文件添加,并压缩) 使用拖拽的方式实现列出需要压缩的文件的操作 选中,点击选中,就可以压缩
*
*/
public class ZipperFrame extends JFrame {
private JPanel contentPane;
private JTable table;
private ButtonGroup radioButtonGroup;
// private ButtonGroup checkButtonGroup;
enum PressType {
ZIP("zip"), JAR("jar"), GZIP("gzip"), SEVEN_ZIP("7z");
private String pressTypeName;
private PressType(String pressTypeName) {
this.pressTypeName = pressTypeName;
}
public String getPressTypeName() {
return pressTypeName;
}
}
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager
.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(ZipFileExployerJFrame.class.getName())
.log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(ZipFileExployerJFrame.class.getName())
.log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(ZipFileExployerJFrame.class.getName())
.log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(ZipFileExployerJFrame.class.getName())
.log(java.util.logging.Level.SEVERE, null, ex);
}
try {
ZipperFrame frame = new ZipperFrame();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public ZipperFrame() {
setTitle("文件压缩器-By Hy");
setBackground(Color.WHITE);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 637, 454);
setLocationRelativeTo(null);
contentPane = new JPanel();
contentPane.setBackground(Color.WHITE);
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JPanel topPanel = new JPanel();
topPanel.setBackground(Color.WHITE);
JLabel pressTypeLbl = new JLabel("压缩类型");
pressTypeLbl.setFont(new Font("宋体", Font.PLAIN, 15));
pressTypeLbl.setBackground(Color.WHITE);
topPanel.add(pressTypeLbl);
PressType[] values = PressType.values();
radioButtonGroup = new ButtonGroup();
for (PressType pressType : values) {
JRadioButton zipRadioButton = new JRadioButton(pressType.pressTypeName);
zipRadioButton.setFont(new Font("宋体", Font.PLAIN, 15));
zipRadioButton.setBackground(Color.WHITE);
zipRadioButton.setSelected(true);
radioButtonGroup.add(zipRadioButton);
topPanel.add(zipRadioButton);
}
JButton pressButton = new JButton("压缩");
pressButton.setFont(new Font("宋体", Font.PLAIN, 15));
pressButton.setFocusable(false);
pressButton.addActionListener(this::onClickZipButton);
// pressButton.setBackground(Color.WHITE);
topPanel.add(pressButton);
contentPane.add(topPanel, BorderLayout.NORTH);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setFont(new Font("宋体", Font.PLAIN, 15));
scrollPane.setBackground(Color.WHITE);
contentPane.add(scrollPane, BorderLayout.CENTER);
table = new JTable() {
@Override
public boolean isCellEditable(int row, int column) {
return column==0;
}
};
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
table.setFont(new Font("宋体", Font.PLAIN, 15));
table.setFillsViewportHeight(true);
scrollPane.setViewportView(table);
DropTarget dropTarget = new DropTarget(table, DnDConstants.ACTION_COPY_OR_MOVE, new TableDropTargetListener());
table.setDropTarget(dropTarget);
DefaultTableModel dataModel = buildTableModel();
// 修改表为不可编辑的
table.setModel(dataModel);
JPopupMenu popupMenu = new JPopupMenu();
addPopup(table, popupMenu);
JMenuItem removeMenuItem = new JMenuItem("移除");
removeMenuItem.addActionListener(this::onClickRemoveMenuItem);
popupMenu.add(removeMenuItem);
JTableHeader tableHeader = table.getTableHeader();
tableHeader.getColumnModel().getColumn(0).setPreferredWidth(50);
tableHeader.getColumnModel().getColumn(0).setWidth(50);
table.getColumnModel().getColumn(0).setPreferredWidth(50);
table.getColumnModel().getColumn(0).setWidth(50);
table.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
tableHeader.setResizingAllowed(false);
tableHeader.setReorderingAllowed(false);
int columnCount = table.getColumnCount();
/*
* table.getColumnModel().getColumn(1).setCellRenderer(new
* FileNameCellRender());
*/
table.getColumnModel().getColumn(0).setCellRenderer(new CheckBoxCellRender());
table.removeColumn(table.getColumnModel().getColumn(4)); // 隐藏file这一列
table.getColumnModel().getColumn(0).setCellEditor(new BooleanEditor());
// checkButtonGroup = new ButtonGroup();
}
PressType useCompressType = null;
// 处理当前的点击事件,点击压缩按钮触发的操作
private void onClickZipButton(ActionEvent e) {
useCompressType = null;
Enumeration<AbstractButton> elements = radioButtonGroup.getElements();
while (elements.hasMoreElements()) {
JRadioButton radionButton = (JRadioButton) elements.nextElement();
if (radionButton.isSelected()) {
String text = radionButton.getText();
if (text.equals("7z")) {
useCompressType = PressType.SEVEN_ZIP;
break;
}
text = text.toUpperCase();
useCompressType = PressType.valueOf(text);
break;
}
}
if (useCompressType == null) {
JOptionPane.showMessageDialog(null, "未选择任何压缩类型", "错误", JOptionPane.ERROR_MESSAGE);
return;
}
System.out.println("使用压缩方式:" + useCompressType);
DefaultTableModel model = (DefaultTableModel) table.getModel();
boolean validateSuccess = true; // 对选中的文件进行校验
for (int i = 0; i < model.getRowCount(); i++) {
Object valueAt = model.getValueAt(i, 4);
System.out.println("使用压缩文件:" + valueAt);
}
// 这里显示一个弹窗,并可以输入保存的文件名称
showFileChooseDialog();
}
Dialog dialog = null;
private File saveZipDirFile;
private String saveZipFileName; // 保存的文件名称
public void setSaveZipDirFile(File saveZipDirFile) {
this.saveZipDirFile = saveZipDirFile;
}
public void setSaveZipFileName(String saveZipFileName) {
this.saveZipFileName = saveZipFileName;
}
private void showFileChooseDialog() {
int rowCount = table.getModel().getRowCount();
if (rowCount <= 0) {
System.out.println("未添加任何需要压缩的文件!");
return;
}
Dialog dialog = new ZipperChooseFileDialog(this, true);
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
System.out.println("用户是否选择文件:" + saveZipDirFile + ",保存的文件名为:" + saveZipFileName);
if (saveZipDirFile == null) {
return;
}
if (saveZipFileName == null || "".equals(saveZipFileName.trim())) {
return;
}
if (saveZipDirFile.isDirectory()) {
List<File> needZipFiles = new ArrayList<>(rowCount);
for (int i = 0; i < rowCount; i++) {
Object fileObject = table.getModel().getValueAt(i, 4);
needZipFiles.add((File) fileObject);
}
// 将文件压缩到指定的位置
String saveZipFilePath = saveZipDirFile.getAbsolutePath() + File.separator + saveZipFileName;
File saveZipFile = new File(saveZipFilePath);
// 开始压缩
System.out.println("使用压缩方式:" + useCompressType);
writeZipFile(needZipFiles, saveZipFile, useCompressType);
}
}
// 将需要压缩的指定的文件,压缩到特定的位置上
private void writeZipFile(List<File> needZipFiles, File targetFile, PressType useCompressType) {
CompressorTask compressorTask = new CompressorTask(needZipFiles, targetFile, useCompressType);
SimpleProgressBarPanel simpleProgressBarPanel = new SimpleProgressBarPanel(compressorTask);
JDialog jDialog = new JDialog(this, "正在压缩文件:" + targetFile.getAbsolutePath(), true);
jDialog.setBackground(Color.WHITE);
jDialog.setSize(500, 400);
jDialog.setPreferredSize(new Dimension(500, 400));
jDialog.setLocationRelativeTo(null);
jDialog.setResizable(true);
jDialog.getContentPane().add(simpleProgressBarPanel);
jDialog.pack();
jDialog.setVisible(true);
// JOptionPane.showMessageDialog(null, "压缩失败!\n原因:" + e.getMessage(), "错误",
// JOptionPane.ERROR_MESSAGE);
}
// 使用压缩任务
class CompressorTask extends SimpleTask {
private List<File> needZipFiles;
private File targetFile;
private PressType useCompressType;
public CompressorTask(List<File> needZipFiles, File targetFile, PressType useCompressType) {
this.needZipFiles = needZipFiles;
this.targetFile = targetFile;
this.useCompressType = useCompressType;
}
@Override
protected Void doInBackground() throws Exception {
ZipCompressor zipCompressor = null;
switch (useCompressType) {
case SEVEN_ZIP:
zipCompressor = new SevenZCompressor();
break;
case GZIP:
zipCompressor = new GzipCompressor();
break;
case ZIP:
case JAR:
zipCompressor = new ZipCompressorImpl();
break;
}
zipCompressor.compress(needZipFiles, targetFile, new CompressCallback() {
@Override
public void updateProgressNum(int res) {
getProgressBar().setValue(res);
System.out.println("当前百分比:" + res);
setProgress(Math.min(res, 100));
}
@Override
public void updateOutput(String text) {
getTaskOutput().append(text + "\n");
}
});
return null;
}
}
// 响应右键触发的移除菜单项
private void onClickRemoveMenuItem(ActionEvent e) {
int selectedRowCount = table.getSelectedRowCount();
if (selectedRowCount <= 0) {
return;
}
int[] selectedRows = table.getSelectedRows();
// System.out.println("开始移除数据" + Arrays.toString(selectedRows));
DefaultTableModel model = (DefaultTableModel) table.getModel();
// 从末尾开始移除数据
for (int i = selectedRows.length - 1; i >= 0; i--) {
int rowIndex = selectedRows[i];
model.removeRow(rowIndex);
}
// 重新修改当前的序号
int rowCount = model.getRowCount();
for (int i = 0; i < rowCount; i++) {
model.setValueAt(String.valueOf(i + 1), i, 0);
}
}
private DefaultTableModel buildTableModel() {
DefaultTableModel defaultTableModel = new DefaultTableModel();
defaultTableModel.setDataVector(new Vector(), buildTableColumnVector());
return defaultTableModel;
}
private Vector buildTableColumnVector() {
Vector tableColumnVector = new Vector(5);
tableColumnVector.add("序号");
tableColumnVector.add("文件名称");
tableColumnVector.add("文件大小");
tableColumnVector.add("添加时间");
tableColumnVector.add("文件对象");
return tableColumnVector;
}
/* List<JCheckBox> jcheckBoxes = new ArrayList<>(); */
/*
* class FileNameCellRender implements TableCellRenderer { private JLabel jLabel
* = new JLabel();
*
* @Override public Component getTableCellRendererComponent(JTable table, Object
* value, boolean isSelected, boolean hasFocus, int row, int column) {
* jLabel.setOpaque(true); jLabel.setText((String)value); if (isSelected) {
* jLabel.setBackground(Color.RED); } else { jLabel.setBackground(Color.WHITE);
* } return jLabel; }
*
* }
*/
class CheckBoxCellRender implements TableCellRenderer {
private JCheckBox jcheckBox = new JCheckBox();
public CheckBoxCellRender() {
jcheckBox.setHorizontalAlignment(JCheckBox.CENTER);
jcheckBox.setOpaque(true);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
jcheckBox.setSelected(Boolean.valueOf(String.valueOf(value)));
// 点击事件不会生效的
/*
* jcheckBox.addActionListener(new ActionListener() {
*
* @Override public void actionPerformed(ActionEvent e) {
* System.out.println("on click!");
*
* } });
*/
//System.out.println("value="+value);
// 若这个checkbox被选中那么这一行应该被选中,否则取消这一行的选中效果
if(jcheckBox.isSelected()) {
table.addRowSelectionInterval(row, row);
}else {
table.removeRowSelectionInterval(row, row);
}
if (isSelected) {
jcheckBox.setBackground(new Color(57, 105, 138));
} else {
//jcheckBox.setSelected(false);
if(row%2!=0) {
jcheckBox.setBackground(new Color(242, 242, 242));
}else {
jcheckBox.setBackground(Color.WHITE);
}
}
return jcheckBox;
}
}
class BooleanEditor extends DefaultCellEditor {
public BooleanEditor() {
super(new JCheckBox());
JCheckBox checkBox = (JCheckBox)getComponent();
checkBox.setHorizontalAlignment(JCheckBox.CENTER);
}
}
class TableDropTargetListener implements DropTargetListener {
@Override
public void dragEnter(DropTargetDragEvent dtde) {
// TODO Auto-generated method stub
}
@Override
public void dragOver(DropTargetDragEvent dtde) {
// TODO Auto-generated method stub
}
@Override
public void dropActionChanged(DropTargetDragEvent dtde) {
// TODO Auto-generated method stub
}
@Override
public void dragExit(DropTargetEvent dte) {
// TODO Auto-generated method stub
}
@Override
public void drop(DropTargetDropEvent dtde) {
if (!dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
dtde.rejectDrop();
return;
}
try {
dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
List<File> files = (List<File>) dtde.getTransferable().getTransferData(DataFlavor.javaFileListFlavor);
// System.out.println("用户选择文件:" + files.size());
DefaultTableModel model = (DefaultTableModel) table.getModel();
int rowCount = model.getRowCount();
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (int i = 0; i < files.size(); i++) {
File file = files.get(i);
String seq = String.valueOf(rowCount + i + 1);
String fileName = file.getName();
String length = String.valueOf(file.length());
String createTime = format.format(date);
JCheckBox jCheckBox = new JCheckBox();
//jCheckBox.setText("666+" + rowCount);
// jCheckBox.putClientProperty("id", seq);
jCheckBox.addActionListener(ZipperFrame.this::onChecked);
// checkButtonGroup.add(jCheckBox);
model.addRow(new Object[] { "false", file.getName(), length, createTime, file });
}
} catch (UnsupportedFlavorException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
dtde.dropComplete(true);
}
}
List<Integer> checkedList = new ArrayList<>();
private void onChecked(ActionEvent event) {
JCheckBox checkBox = (JCheckBox) event.getSource();
if (checkBox.isSelected()) {
checkedList.add(Integer.valueOf(checkBox.getText()));
} else {
checkedList.remove(Integer.valueOf(checkBox.getText()));
}
System.out.println("用户选中:" + checkedList);
}
private static void addPopup(Component component, final JPopupMenu popup) {
component.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
if (e.isPopupTrigger()) {
showMenu(e);
}
}
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
showMenu(e);
}
}
private void showMenu(MouseEvent e) {
popup.show(e.getComponent(), e.getX(), e.getY());
}
});
}
}
2. 其他类
==保存文件的弹窗类:ZipperChooseFileDialog ==
package com.hy.test;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import java.awt.Color;
import javax.swing.UIManager;
public class ZipperChooseFileDialog extends JDialog {
private final JPanel contentPanel = new JPanel();
private JTextField textField;
private JLabel chooseDirLbl;
/**
* Launch the application.
*/
/*
* public static void main(String[] args) { try { ZipperChooseFileDialog dialog
* = new ZipperChooseFileDialog();
* dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
* dialog.setVisible(true); } catch (Exception e) { e.printStackTrace(); } }
*/
private ZipperFrame jFrame;
/**
* Create the dialog.
*/
public ZipperChooseFileDialog(ZipperFrame jframe,boolean modal) {
this.jFrame =jframe;
setModal(modal);
setBackground(Color.WHITE);
setResizable(false);
setTitle("信息");
setBounds(100, 100, 450, 231);
getContentPane().setLayout(new BorderLayout());
contentPanel.setBackground(Color.WHITE);
contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
getContentPane().add(contentPanel, BorderLayout.CENTER);
contentPanel.setLayout(null);
JLabel lblNewLabel = new JLabel("文件名称");
lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER);
lblNewLabel.setBounds(33, 30, 157, 21);
contentPanel.add(lblNewLabel);
textField = new JTextField();
textField.setBounds(204, 30, 199, 24);
contentPanel.add(textField);
textField.setColumns(10);
JButton btnNewButton = new JButton("选择文件夹");
btnNewButton.addActionListener(this::onChooseFileButtonClick);
btnNewButton.setBackground(UIManager.getColor("Button.background"));
btnNewButton.setBounds(60, 86, 116, 27);
contentPanel.add(btnNewButton);
chooseDirLbl = new JLabel("");
chooseDirLbl.setBounds(204, 86, 199, 27);
contentPanel.add(chooseDirLbl);
{
JPanel buttonPane = new JPanel();
buttonPane.setBackground(Color.WHITE);
buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
getContentPane().add(buttonPane, BorderLayout.SOUTH);
{
JButton okButton = new JButton("确定");
//okButton.setBackground(UIManager.getColor("Button.background"));
okButton.setActionCommand("OK");
buttonPane.add(okButton);
okButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String text = textField.getText();
if(text==null||"".equals(text.trim())) {
JOptionPane.showMessageDialog(null, "当前输入的文件名必须不是空", "错误", JOptionPane.ERROR_MESSAGE);
return;
}
jFrame.setSaveZipFileName(text.trim());
setVisible(false);
}
});
getRootPane().setDefaultButton(okButton);
}
{
JButton cancelButton = new JButton("取消");
//cancelButton.setBackground(UIManager.getColor("Button.background"));
cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
setVisible(false);
}
});
cancelButton.setActionCommand("Cancel");
buttonPane.add(cancelButton);
}
}
}
private void onChooseFileButtonClick(ActionEvent e) {
JFileChooser jc = new JFileChooser();
jc.setBackground(Color.WHITE);
jc.setDialogTitle("选择保存的文件夹");
jc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int showDialog = jc.showDialog(this, "确定");
if(showDialog == JFileChooser.APPROVE_OPTION) {
System.out.println("已同意");
File selectedFile = jc.getSelectedFile();
chooseDirLbl.setText(selectedFile.getAbsolutePath());
this.jFrame.setSaveZipDirFile(selectedFile);
}else {
this.jFrame.setSaveZipDirFile(null);
}
}
}
public interface ZipCompressor {
void compress(List<File> files, File targetFile,CompressCallback compressCallback) throws IOException;
}
压缩回调类,回显百分比和进度
public interface CompressCallback {
// 更新当前的处理进度
void updateProgressNum(int res);
// 更新当前的输出信息
void updateOutput(String text);
}
ZipCompressorImpl类
package com.hy.test.zip.compress.impl;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import com.hy.test.zip.compress.CompressCallback;
import com.hy.test.zip.compress.ZipCompressor;
public class ZipCompressorImpl implements ZipCompressor {
byte[] buffer = new byte[1024];// 使用的缓冲区
@Override
public void compress(List<File> files, File targetFile,CompressCallback compressCallback) throws IOException {
int total = files.size();
try (ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(targetFile))) {
for (int i = 0; i < files.size(); i++) {
File file = files.get(i);
compressCallback.updateProgressNum(((i)*100/total));
compressCallback.updateOutput("正在压缩:"+file.getAbsolutePath());
// 使用文件的情况下
if (file.isFile()) {
putFileToZip(file, file.getName(), zipOutputStream);
} else {
putDirToZip(file,file.getName(),file.getAbsolutePath(), zipOutputStream);
}
}
}
compressCallback.updateProgressNum(100);
}
// 直接将文件的实体加入其中即可
private void putFileToZip(File file, String entryName, ZipOutputStream zipOutputStream) throws IOException {
ZipEntry zipEntry = new ZipEntry(entryName);
System.out.println("构建压缩实体FILE:"+entryName);
zipOutputStream.putNextEntry(zipEntry);
int len = -1;
// 写出单条数据
try (FileInputStream fis = new FileInputStream(file)) {
while ((len = fis.read(buffer)) != -1) {
zipOutputStream.write(buffer, 0, len);
}
}
zipOutputStream.closeEntry();
}
private void putDirToZip(File dir,String rootDirName,String rootDirPath, ZipOutputStream zipOutputStream) throws IOException {
File[] listFiles = dir.listFiles();
if (listFiles == null || listFiles.length == 0) {
return;
}
for (File file : listFiles) {
if (file.isFile()) {
String absolutePath = file.getAbsolutePath();
String name = absolutePath.replace(rootDirPath, "").replace("\\", "/");
putFileToZip(file, rootDirName +name , zipOutputStream);
}
if (file.isDirectory()) {
putDirToZip(file,rootDirName,rootDirPath, zipOutputStream);
}
}
}
}
SevenZCompressor压缩类
package com.hy.test.zip.compress.impl;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZOutputFile;
import com.hy.test.zip.compress.CompressCallback;
import com.hy.test.zip.compress.ZipCompressor;
/**
*
* @author hy
* @createTime 2021-06-20 13:22:37
* @description 当前内容主要为测试和使用7z进行压缩
*
*/
public class SevenZCompressor implements ZipCompressor {
byte[] buffer = new byte[1024];
@Override
public void compress(List<File> files, File targetFile, CompressCallback compressCallback) throws IOException {
int total = files.size();
try (SevenZOutputFile sevenZOutput = new SevenZOutputFile(targetFile);) {
for (int i = 0; i < files.size(); i++) {
File inFile = files.get(i);
compressCallback.updateProgressNum(((i) * 100 / total));
compressCallback.updateOutput("正在压缩:" + inFile.getAbsolutePath());
System.out.println("正在压缩:"+ inFile.getAbsolutePath());
if (!inFile.isDirectory()) {
putFileInZip(inFile, inFile.getName(), sevenZOutput,compressCallback);
} else {
putDirInZip(inFile, inFile.getAbsolutePath(), inFile.getName(), sevenZOutput,compressCallback);
}
}
}
compressCallback.updateProgressNum(100);
}
private void putFileInZip(File file, String entryName, SevenZOutputFile sevenZOutput,CompressCallback compressCallback) throws IOException {
SevenZArchiveEntry entry = sevenZOutput.createArchiveEntry(file, entryName);
sevenZOutput.putArchiveEntry(entry);
System.out.println("正在压缩FILE:"+ file.getAbsolutePath());
compressCallback.updateOutput("正在压缩FILE:" + file.getAbsolutePath());
int len = 0;
try (FileInputStream fis = new FileInputStream(file)) {
while ((len = fis.read(buffer)) != -1) {
sevenZOutput.write(buffer, 0, len);
}
}
sevenZOutput.closeArchiveEntry();
}
private void putDirInZip(File dirFile, String rootDirPath, String rootDirName, SevenZOutputFile sevenZOutput,CompressCallback compressCallback)
throws IOException {
File[] listFiles = dirFile.listFiles();
if (listFiles == null || listFiles.length == 0) {
return;
}
for (File file : listFiles) {
if (file.isFile()) {
String absolutePath = file.getAbsolutePath();
String name = absolutePath.replace(rootDirPath, "").replace("\\", "/");
putFileInZip(file, rootDirName + name, sevenZOutput,compressCallback);
}
if (file.isDirectory()) {
putDirInZip(file, rootDirPath, rootDirName, sevenZOutput,compressCallback);
}
}
}
}
GzipCompressor 压缩类
package com.hy.test.zip.compress.impl;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
import com.hy.test.zip.compress.CompressCallback;
import com.hy.test.zip.compress.ZipCompressor;
/**
*
* @author hy
* @createTime 2021-06-20 13:17:57
* @description 当前内容主要为测试和使用apache compress(详细明细查看官方文档)
*
*/
public class GzipCompressor implements ZipCompressor{
byte[] buffer = new byte[1024];
@Override
public void compress(List<File> files, File targetFile,CompressCallback compressCallback) throws IOException {
int total = files.size();
try (GzipCompressorOutputStream gzipos = new GzipCompressorOutputStream(new FileOutputStream(targetFile));
TarArchiveOutputStream tarArchiveOutput = new TarArchiveOutputStream(gzipos);){
for (int i = 0; i < files.size(); i++) {
File inFile = files.get(i);
compressCallback.updateProgressNum(((i)*100/total));
compressCallback.updateOutput("正在压缩:"+inFile.getAbsolutePath());
if (!inFile.isDirectory()) {
putFileInZip(inFile, inFile.getName(), tarArchiveOutput,compressCallback);
} else {
putDirInZip(inFile, inFile.getAbsolutePath(), inFile.getName(), tarArchiveOutput,compressCallback);
}
}
}
compressCallback.updateProgressNum(100);
}
private void putFileInZip(File file, String entryName,
TarArchiveOutputStream tarArchiveOutput,
CompressCallback compressCallback) throws IOException {
ArchiveEntry entry = tarArchiveOutput.createArchiveEntry(file, entryName);
tarArchiveOutput.putArchiveEntry(entry);
System.out.println("正在压缩FILE:"+ file.getAbsolutePath());
int len = 0;
try (FileInputStream fis = new FileInputStream(file)) {
while ((len = fis.read(buffer)) != -1) {
tarArchiveOutput.write(buffer, 0, len);
}
}
tarArchiveOutput.closeArchiveEntry();
}
private void putDirInZip(File dirFile, String rootDirPath,
String rootDirName,
TarArchiveOutputStream tarArchiveOutput,
CompressCallback compressCallback)
throws IOException {
File[] listFiles = dirFile.listFiles();
if (listFiles == null || listFiles.length == 0) {
return;
}
for (File file : listFiles) {
if (file.isFile()) {
String absolutePath = file.getAbsolutePath();
String name = absolutePath.replace(rootDirPath, "").replace("\\", "/");
putFileInZip(file, rootDirName + name, tarArchiveOutput,compressCallback);
}
if (file.isDirectory()) {
putDirInZip(file, rootDirPath, rootDirName, tarArchiveOutput,compressCallback);
}
}
}
}
其实压缩类都差不多
进度条类:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import com.hy.test.zip.expander.ExpanderCallback;
import com.hy.test.zip.expander.JarExpander;
import java.beans.*;
import java.io.File;
import java.util.Random;
/**
*
* @author hy
* @createTime 2022-10-08 12:59:49
* @description 一个解压进度条和明细的面板
*
*/
public class SimpleProgressBarPanel extends JPanel implements ActionListener, PropertyChangeListener {
private JProgressBar progressBar;
private JTextArea taskOutput;
private SwingWorker swingWorker;
// private File zipFile;
// private File dirFile;
public JProgressBar getProgressBar() {
return progressBar;
}
public JTextArea getTaskOutput() {
return taskOutput;
}
public SimpleProgressBarPanel(SimpleTask task) {
super(new BorderLayout());
progressBar = new JProgressBar(0, 100);
progressBar.setValue(0);
progressBar.setStringPainted(true);
taskOutput = new JTextArea(5, 20);
taskOutput.setMargin(new Insets(5, 5, 5, 5));
taskOutput.setEditable(false);
JPanel panel = new JPanel();
panel.add(progressBar);
add(panel, BorderLayout.PAGE_START);
add(new JScrollPane(taskOutput), BorderLayout.CENTER);
setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
// 转发处理显示给task类
task.setProgressBar(progressBar);
task.setTaskOutput(taskOutput);
task.setJpanel(this);
this.swingWorker = task;
this.actionPerformed(null);
}
/**
* Invoked when the user presses the start button.
*/
public void actionPerformed(ActionEvent evt) {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
// Instances of javax.swing.SwingWorker are not reusuable, so
// we create new instances as needed.
// task = new Task();
swingWorker.addPropertyChangeListener(this);
swingWorker.execute();
}
/**
* Invoked when task's progress property changes.
*/
@Override
public void propertyChange(PropertyChangeEvent evt) {
/*
* if ("progress" == evt.getPropertyName()) { int progress = (Integer)
* evt.getNewValue(); progressBar.setValue(progress);
* taskOutput.append(String.format("Completed %d%% of task.\n",
* task.getProgress())); }
*/
}
进度条的任务处理类:
package com.hy.test.progressbar;
import java.awt.Toolkit;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;
/**
*
* @author hy
* @createTime 2022-10-12 10:46:20
* @description 使用简单的任务进行处理操作,将当前的操作
*
*/
public abstract class SimpleTask extends SwingWorker<Void, Void>{
private JProgressBar progressBar;
private JTextArea taskOutput;
private JPanel jpanel;
public JPanel getJpanel() {
return jpanel;
}
public void setJpanel(JPanel jpanel) {
this.jpanel = jpanel;
}
public void setProgressBar(JProgressBar progressBar) {
this.progressBar = progressBar;
}
public void setTaskOutput(JTextArea taskOutput) {
this.taskOutput = taskOutput;
}
public JProgressBar getProgressBar() {
return progressBar;
}
public JTextArea getTaskOutput() {
return taskOutput;
}
/*
* Executed in event dispatching thread
*/
@Override
public void done() {
Toolkit.getDefaultToolkit().beep();
getJpanel().setCursor(null); // turn off the wait cursor
getTaskOutput().append("Done!\n");
}
}
5.总结
- 通过编写了解了压缩文件的主要Entry的实体和名称方式
- 可以在JTable中自定义单元格的渲染格式,但是对于要对单个单元格进行响应点击操作,必须使用Editor,但是本身的CheckBox或者按钮绑定了点击事件是不会触发的