My program copy zipFile to temp directory. // 33
If "new" folder is in upmost tree, checking whether that folder have file with the same name like fileToCopy, and change the file. // 73
(maybe I don't understand task correctly but I see in exaple of result that tree looks like: upmostTree/new/fileToCopy
(My program don't accept when "new" directory is deeper like: someDir/anotherDirectory/new/file.))
If not, create new folder with copy of file // 89
Everything working but still everything on red. What I have to do!?
Maybe I don't see something correct (possible because knowledge which CG gave me is not enough to do it), or maybe I don't understand task cleary (5 sentences for explain whole task logic and condition...)
Please give me some hint or something.
package com.codegym.task.task31.task3105;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
/*
Adding a file to an archive
C:\\Users\\Admin\\Desktop\\result.txt
C:\Users\Admin\Desktop\Zip.zip
C:\Users\Admin\Desktop\temp
*/
public class Solution {
public static void main(String[] args) throws IOException {
String fileToCopy = args[0]; //args[0];
String zipFile = args[1]; //args[1];
String tempPath = "C:\\Users\\Admin\\Desktop\\temp";
File tempDirectory = new File(tempPath);
String fileName = Paths.get(fileToCopy).getFileName().toString();
// Check if args[0] & args[1] are valid
if (!isValidPath(fileToCopy) || !isValidZipPath(zipFile)) return;
// First part: Copying data from zipFile to tempZip
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) {
ZipEntry zipEntry;
while ((zipEntry = zis.getNextEntry()) != null) {
File newFile = newFile(tempDirectory, zipEntry);
if (zipEntry.isDirectory()) {
if (!newFile.isDirectory() && !newFile.mkdirs()) {
throw new IOException("Failed to create directory " + newFile);
}
} else {
// fix for Windows-created archives
File parent = newFile.getParentFile();
if (!parent.isDirectory() && !parent.mkdirs()) {
throw new IOException("Failed to create directory " + parent);
}
// write file content
byte[] buffer = new byte[1024];
try (FileOutputStream fos = new FileOutputStream(newFile)) {
int len;
while ((len = zis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
}
}
}
zis.closeEntry();
} catch (IOException e) {
e.printStackTrace();
}
// Delete and override by ready for it copy file
Files.deleteIfExists(Paths.get(zipFile));
// Second part: Iterating through temp checking for "new" folder and whether adding or replacing file
class MyVisitor extends SimpleFileVisitor<Path> {
public boolean hasNewDirectory = false;
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
if (file.getFileName().toString().equals(fileName)
&& file.getParent().getFileName().toString().equals("new")
// check if "new" directory is first subtree from temp directory
&& file.getParent().getParent().getFileName().toString().equals(tempDirectory.getName())) {
Files.copy(Paths.get(fileToCopy), file, StandardCopyOption.REPLACE_EXISTING);
hasNewDirectory = true;
}
return FileVisitResult.CONTINUE;
}
}
MyVisitor visitor = new MyVisitor();
Files.walkFileTree(tempDirectory.toPath(), visitor);
// Creating "new" directory if it needed
if (!visitor.hasNewDirectory) {
createNewDirWithCopiedFile(tempPath, fileToCopy);
}
// Third part: writing temp file back to zip file
try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile))) {
zipDirectory(tempPath, tempPath, zos);
zos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static boolean isValidZipPath(String path) {
if (!isValidPath(path))
return false;
return path.endsWith(".zip");
}
public static boolean isValidPath(String path) {
try {
Paths.get(path);
} catch (InvalidPathException | NullPointerException ex) {
return false;
}
return true;
}
public static File newFile(File destinationDir, ZipEntry zipEntry) throws IOException {
File destFile = new File(destinationDir, zipEntry.getName());
String destDirPath = destinationDir.getCanonicalPath();
String destFilePath = destFile.getCanonicalPath();
if (!destFilePath.startsWith(destDirPath + File.separator)) {
throw new IOException("Entry is outside of the target dir: " + zipEntry.getName());
}
return destFile;
}
private static void zipDirectory(String basePath, String currentPath, ZipOutputStream zos) throws IOException {
File dir = new File(currentPath);
File[] files = dir.listFiles();
byte[] buffer = new byte[1024];
int bytesRead;
for (File file : files) {
if (file.isDirectory()) {
zipDirectory(basePath, file.getAbsolutePath(), zos);
} else {
FileInputStream fis = new FileInputStream(file);
String entryName = file.getAbsolutePath().substring(basePath.length() + 1);
ZipEntry entry = new ZipEntry(entryName);
zos.putNextEntry(entry);
while ((bytesRead = fis.read(buffer)) != -1) {
zos.write(buffer, 0, bytesRead);
}
zos.closeEntry();
fis.close();
}
}
}
private static void createNewDirWithCopiedFile(String tempPath, String fileToCopy) {
Path newDir = Paths.get(tempPath, "new");
Path source = Paths.get(fileToCopy);
try {
Files.createDirectory(newDir);
Path destinationPath = newDir.resolve(source.getFileName());
Files.copy(source, destinationPath, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
e.printStackTrace();
}
}
}