added support for zip
This commit is contained in:
parent
5a7312eb8e
commit
dcc9a6a418
@ -8,6 +8,7 @@ import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.*;
|
||||
|
||||
/**
|
||||
* Service for file operations - copy, move, delete, etc.
|
||||
@ -237,6 +238,100 @@ public class FileOperations {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Zip files/directories into a target zip file
|
||||
*/
|
||||
public static void zip(List<FileItem> items, File targetZipFile, ProgressCallback callback) throws IOException {
|
||||
try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(targetZipFile))) {
|
||||
int current = 0;
|
||||
int total = items.size();
|
||||
|
||||
for (FileItem item : items) {
|
||||
current++;
|
||||
File source = item.getFile();
|
||||
if (callback != null) {
|
||||
callback.onProgress(current, total, source.getName());
|
||||
}
|
||||
addToZip(source, source.getName(), zos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void addToZip(File fileToZip, String fileName, ZipOutputStream zos) throws IOException {
|
||||
if (fileToZip.isHidden()) {
|
||||
return;
|
||||
}
|
||||
if (fileToZip.isDirectory()) {
|
||||
if (fileName.endsWith("/")) {
|
||||
zos.putNextEntry(new ZipEntry(fileName));
|
||||
zos.closeEntry();
|
||||
} else {
|
||||
zos.putNextEntry(new ZipEntry(fileName + "/"));
|
||||
zos.closeEntry();
|
||||
}
|
||||
File[] children = fileToZip.listFiles();
|
||||
if (children != null) {
|
||||
for (File childFile : children) {
|
||||
addToZip(childFile, fileName + "/" + childFile.getName(), zos);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
try (FileInputStream fis = new FileInputStream(fileToZip)) {
|
||||
ZipEntry zipEntry = new ZipEntry(fileName);
|
||||
zos.putNextEntry(zipEntry);
|
||||
byte[] bytes = new byte[1024];
|
||||
int length;
|
||||
while ((length = fis.read(bytes)) >= 0) {
|
||||
zos.write(bytes, 0, length);
|
||||
}
|
||||
zos.closeEntry();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unzip a zip file into a target directory
|
||||
*/
|
||||
public static void unzip(File zipFile, File targetDirectory, ProgressCallback callback) throws IOException {
|
||||
if (!targetDirectory.exists()) {
|
||||
Files.createDirectories(targetDirectory.toPath());
|
||||
}
|
||||
|
||||
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) {
|
||||
ZipEntry entry;
|
||||
// First pass or estimated count could be done, but keep it simple for now
|
||||
while ((entry = zis.getNextEntry()) != null) {
|
||||
File newFile = new File(targetDirectory, entry.getName());
|
||||
|
||||
if (callback != null) {
|
||||
callback.onProgress(0, 0, entry.getName());
|
||||
}
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
if (!newFile.isDirectory() && !newFile.mkdirs()) {
|
||||
throw new IOException("Failed to create directory " + newFile);
|
||||
}
|
||||
} else {
|
||||
// create parent directories if they don't exist
|
||||
File parent = newFile.getParentFile();
|
||||
if (!parent.isDirectory() && !parent.mkdirs()) {
|
||||
throw new IOException("Failed to create directory " + parent);
|
||||
}
|
||||
|
||||
// write file content
|
||||
try (FileOutputStream fos = new FileOutputStream(newFile)) {
|
||||
byte[] buffer = new byte[1024];
|
||||
int len;
|
||||
while ((len = zis.read(buffer)) > 0) {
|
||||
fos.write(buffer, 0, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
zis.closeEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// legacy matchesPattern removed — filename wildcard handling is done via a precompiled Pattern
|
||||
|
||||
/**
|
||||
|
||||
@ -423,6 +423,16 @@ public class MainWindow extends JFrame {
|
||||
KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0),
|
||||
JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
|
||||
// Alt+F5 - Zip
|
||||
rootPane.registerKeyboardAction(e -> zipFiles(),
|
||||
KeyStroke.getKeyStroke(KeyEvent.VK_F5, InputEvent.ALT_DOWN_MASK),
|
||||
JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
|
||||
// Alt+F9 - Unzip
|
||||
rootPane.registerKeyboardAction(e -> unzipFiles(),
|
||||
KeyStroke.getKeyStroke(KeyEvent.VK_F9, InputEvent.ALT_DOWN_MASK),
|
||||
JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
|
||||
// F6 - Move
|
||||
rootPane.registerKeyboardAction(e -> moveFiles(),
|
||||
KeyStroke.getKeyStroke(KeyEvent.VK_F6, 0),
|
||||
@ -701,6 +711,101 @@ public class MainWindow extends JFrame {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Zip selected files
|
||||
*/
|
||||
private void zipFiles() {
|
||||
List<FileItem> selectedItems = activePanel.getSelectedItems();
|
||||
if (selectedItems.isEmpty()) {
|
||||
JOptionPane.showMessageDialog(this,
|
||||
"No files selected",
|
||||
"Zip",
|
||||
JOptionPane.INFORMATION_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
String defaultName;
|
||||
if (selectedItems.size() == 1) {
|
||||
defaultName = selectedItems.get(0).getName();
|
||||
} else {
|
||||
defaultName = activePanel.getCurrentDirectory().getName();
|
||||
if (defaultName == null || defaultName.isEmpty() || defaultName.equals("/") || defaultName.endsWith(":")) {
|
||||
defaultName = "archive";
|
||||
}
|
||||
}
|
||||
|
||||
if (defaultName.contains(".")) {
|
||||
int lastDot = defaultName.lastIndexOf('.');
|
||||
if (lastDot > 0) {
|
||||
defaultName = defaultName.substring(0, lastDot);
|
||||
}
|
||||
}
|
||||
defaultName += ".zip";
|
||||
|
||||
String zipName = JOptionPane.showInputDialog(this, "Enter zip filename:", defaultName);
|
||||
if (zipName == null || zipName.trim().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!zipName.toLowerCase().endsWith(".zip")) {
|
||||
zipName += ".zip";
|
||||
}
|
||||
|
||||
FilePanel targetPanel = (activePanel == leftPanel) ? rightPanel : leftPanel;
|
||||
File targetDir = targetPanel.getCurrentDirectory();
|
||||
File targetZip = new File(targetDir, zipName);
|
||||
|
||||
if (targetZip.exists()) {
|
||||
int confirm = JOptionPane.showConfirmDialog(this,
|
||||
"File already exists. Overwrite?", "Zip", JOptionPane.YES_NO_OPTION);
|
||||
if (confirm != JOptionPane.YES_OPTION) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
final File finalTargetZip = targetZip;
|
||||
performFileOperation(() -> {
|
||||
FileOperations.zip(selectedItems, finalTargetZip, null);
|
||||
}, "Zabaleno do " + zipName, targetPanel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unzip selected zip file
|
||||
*/
|
||||
private void unzipFiles() {
|
||||
List<FileItem> selectedItems = activePanel.getSelectedItems();
|
||||
if (selectedItems.isEmpty()) {
|
||||
JOptionPane.showMessageDialog(this,
|
||||
"No files selected",
|
||||
"Unzip",
|
||||
JOptionPane.INFORMATION_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
File zipFile = selectedItems.get(0).getFile();
|
||||
if (!zipFile.getName().toLowerCase().endsWith(".zip")) {
|
||||
JOptionPane.showMessageDialog(this,
|
||||
"Selected file is not a ZIP archive",
|
||||
"Unzip",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
FilePanel targetPanel = (activePanel == leftPanel) ? rightPanel : leftPanel;
|
||||
File targetDir = targetPanel.getCurrentDirectory();
|
||||
|
||||
int result = JOptionPane.showConfirmDialog(this,
|
||||
String.format("Unzip %s to:\n%s", zipFile.getName(), targetDir.getAbsolutePath()),
|
||||
"Unzip",
|
||||
JOptionPane.OK_CANCEL_OPTION);
|
||||
|
||||
if (result == JOptionPane.OK_OPTION) {
|
||||
performFileOperation(() -> {
|
||||
FileOperations.unzip(zipFile, targetDir, null);
|
||||
}, "Rozbaleno do " + targetDir.getName(), targetPanel);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename selected file
|
||||
*/
|
||||
@ -914,6 +1019,8 @@ public class MainWindow extends JFrame {
|
||||
"Java 11\n\n" +
|
||||
"Keyboard shortcuts:\n" +
|
||||
"F5 - Copy\n" +
|
||||
"Alt+F5 - Zip\n" +
|
||||
"Alt+F9 - Unzip\n" +
|
||||
"F6 - Move\n" +
|
||||
"F7 - New directory\n" +
|
||||
"F8 - Delete\n" +
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user