Java Swing:自定义压缩工具

1. 声明

当前内容主要为使用Swing来实现一个文件压缩器,借助Apache Commons来实现,内容借鉴:官方文档

主要涉及以下Swing组件

  1. JTable中自定义CellRenderer,CellEditor,隐藏列
  2. JProgressorBar的使用
  3. JDialog的使用
  4. 实现拖拽文件到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.总结

  1. 通过编写了解了压缩文件的主要Entry的实体和名称方式
  2. 可以在JTable中自定义单元格的渲染格式,但是对于要对单个单元格进行响应点击操作,必须使用Editor,但是本身的CheckBox或者按钮绑定了点击事件是不会触发的
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值