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.List;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.zip.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service for file operations - copy, move, delete, etc.
|
* 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
|
// 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),
|
KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0),
|
||||||
JComponent.WHEN_IN_FOCUSED_WINDOW);
|
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
|
// F6 - Move
|
||||||
rootPane.registerKeyboardAction(e -> moveFiles(),
|
rootPane.registerKeyboardAction(e -> moveFiles(),
|
||||||
KeyStroke.getKeyStroke(KeyEvent.VK_F6, 0),
|
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
|
* Rename selected file
|
||||||
*/
|
*/
|
||||||
@ -914,6 +1019,8 @@ public class MainWindow extends JFrame {
|
|||||||
"Java 11\n\n" +
|
"Java 11\n\n" +
|
||||||
"Keyboard shortcuts:\n" +
|
"Keyboard shortcuts:\n" +
|
||||||
"F5 - Copy\n" +
|
"F5 - Copy\n" +
|
||||||
|
"Alt+F5 - Zip\n" +
|
||||||
|
"Alt+F9 - Unzip\n" +
|
||||||
"F6 - Move\n" +
|
"F6 - Move\n" +
|
||||||
"F7 - New directory\n" +
|
"F7 - New directory\n" +
|
||||||
"F8 - Delete\n" +
|
"F8 - Delete\n" +
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user