Unable to extract zip file through Java code made in nodeJs code - java

What I want to do, is to create a zip file in nodeJs and later extract it through Java code(An already written Java program to work on the zip).
I am able to create zip file in nodeJs using jszip but my java code is unable to extract that zip file(Though my finder can extract it, even my extract code in nodeJs also works).
nodeJs code to create zip:
this.zip = function (sourceDirectory, zipFile, excludParent) {
var zip = new JSZip();
var list = getFiles(sourceDirectory, excludParent);
for (var i = 0; i < list.length; i++) {
var obj = list[i];
if(typeof(obj.source) == "undefined"){
if (excludParent)
zip.folder(obj.target.substring(obj.target.indexOf("/") + 1));
else
zip.folder(obj.target);
}else {
if (excludParent)
zip.file(obj.target.substring(obj.target.indexOf("/") + 1), fs.readFileSync(obj.target), {base64: true});
else
zip.file(obj.target, fs.readFileSync(obj.target), {base64: true});
}
}
zip.generateNodeStream({type:'nodebuffer', streamFiles:true, compressionOptions:'DEFAULT'})
.pipe(fs.createWriteStream(zipFile))
.on('finish', function () {
console.log(zipFile + " written.");
})
};
var getFiles = function (sourceDirectory, excludeParent) {
var list = [];
if (excludeParent) {
if (fs.lstatSync(sourceDirectory).isDirectory()) {
var fileList = fs.readdirSync(sourceDirectory);
for (var i = 0; i < fileList.length; i++) {
list = list.concat(getFiles_(sourceDirectory + sep, fileList[i]));
}
}
} else {
list = getFiles_("", sourceDirectory);
}
return list;
};
var getFiles_ = function (parentDir, path) {
var list = [];
if (path.indexOf(".") == 0) return list;
if (fs.lstatSync(parentDir + path).isDirectory()) {
list.push({target: parentDir + path});
var fileList = fs.readdirSync(parentDir + path);
for (var i = 0; i < fileList.length; i++) {
list = list.concat(getFiles_(parentDir + path + sep, fileList[i]));
}
} else {
list.push({source: parentDir + path, target: parentDir + path});
}
return list;
};
Java code to extract file:
public void unzip(String zipFilePath, String destDirectory) throws IOException {
File destDir = new File(destDirectory);
if (!destDir.exists()) {
destDir.mkdir();
}
ZipInputStream zipIn = new ZipInputStream(new FileInputStream(zipFilePath));
ZipEntry entry = zipIn.getNextEntry();
// iterates over entries in the zip file
while (entry != null) {
String filePath = destDirectory + File.separator + entry.getName();
if (!entry.isDirectory()) {
// if the entry is a file, extracts it
extractFile(zipIn, filePath);
} else {
// if the entry is a directory, make the directory
File dir = new File(filePath);
dir.mkdirs();
}
zipIn.closeEntry();
entry = zipIn.getNextEntry();
}
zipIn.close();
}
This code throws following stacktrace:
java.util.zip.ZipException: only DEFLATED entries can have EXT descriptor
at java.util.zip.ZipInputStream.readLOC(ZipInputStream.java:310)
at java.util.zip.ZipInputStream.getNextEntry(ZipInputStream.java:122)
at module.builder.ZipUtility.unzip(ZipUtility.java:57)
at module.builder.DataPatcher.unZipAndroidImageFiles(DataPatcher.java:624)
at module.builder.DataPatcher.patchAndroid(DataPatcher.java:145)
at module.builder.FXMLDocumentController$5.call(FXMLDocumentController.java:324)
at module.builder.FXMLDocumentController$5.call(FXMLDocumentController.java:312)
at javafx.concurrent.Task$TaskCallable.call(Task.java:1423)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.lang.Thread.run(Thread.java:745)
This java code works fine if i create a zip file through an application (i.e winzip, winrar, zip made by finder etc.) but it throws ava.util.zip.ZipException: only DEFLATED entries can have EXT descriptor while extracting zip made through above mentioned nodeJs method.

I ran into the same problem today.
The issue is with the streamFiles:true passed as an option to zip.generateNodeStream(). From the docs:
When this options is true, we stream the file and use data descriptors at > the end of the entry. This option uses less memory but some program might > not support data descriptors (and won’t accept the generated zip file).
Removing the streamFiles:true option should work as long as you are not worried about memory usage.

Related

how to copy the contents of a last modified file from a folder to the other folder using java?

i am trying to copy the contents of a last modified file from a folder to the other folder using java
i am able to move the file but i am unable to move the contents of the file
private File getLatestFilefromDir(String dirPath) throws IOException{
File dir = new File(dirPath);
File[] files = dir.listFiles();
if (files == null || files.length == 0) {
return null;
}
File lastModifiedFile = files[0];
for (int i = 1; i < files.length; i++) {
if (lastModifiedFile.lastModified() < files[i].lastModified()) {
lastModifiedFile = files[i];
}
}
String newFilePath = "C:\\newPath\\"+lastModifiedFile.getName();
Path temp = Files.move
(Paths.get(dirPath),
Paths.get(newFilePath ));
if(temp != null)
{
System.out.println("File renamed and moved successfully");
}
else
{
System.out.println("Failed to move the file");
}
return new File(newFilePath );
}
Result : only file is moving but not contents
Rather use the Apache Commons IO library and more specifically org.apache.commons.io.FileUtils. It's a very nice library that works really well with what your trying to do.
File sourceFile = new File(...);
File destinationFile = new File(...);
FileUtils.moveFile(sourceFile, destinationFile);
Used it quite successfully on a small project I did a while back (FilingAssistant)

How to add duplicate file in Zip using ZipEntry

I have a list of files and that list may contains duplicate file name but those files resides in different location with different data. Now when I am trying to add those files in zip I am getting java.lang.Exception: duplicate entry: File1.xlsx. Please suggest how I can add duplicate file names. One solution is like if I can rename the dulpicate file as File , File_1,File_2.. But I am not sure how I can achieve it. Please help !!! Below is my working code if all the file names are unique.
Resource resource = null;
try (ZipOutputStream zippedOut = new ZipOutputStream(response.getOutputStream())) {
for (String file : fileNames) {
resource = new FileSystemResource(file);
if(!resource.exists() && resource != null) {
ZipEntry e = new ZipEntry(resource.getFilename());
//Configure the zip entry, the properties of the file
e.setSize(resource.contentLength());
e.setTime(System.currentTimeMillis());
// etc.
zippedOut.putNextEntry(e);
//And the content of the resource:
StreamUtils.copy(resource.getInputStream(), zippedOut);
zippedOut.closeEntry();
}
}
//zippedOut.close();
zippedOut.finish();
return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=download.zip").body(zippedOut);
} catch (Exception e) {
throw new Exception(e.getMessage());
}
One solution is like if I can rename the duplicate file as File, File_1, File_2, ... But I am not sure how I can achieve it.
Build a Set of names, and append a number to make name unique, if needed, e.g.
Set<String> names = new HashSet<>();
for (String file : fileNames) {
// ...
String name = resource.getFilename();
String originalName = name;
for (int i = 1; ! names.add(name); i++)
name = originalName + "_" + i;
ZipEntry e = new ZipEntry(name);
// ...
}
The code relies on add() returning false if the name is already in the Set, i.e. if name is a duplicate.
This will work even if given names are already numbered, e.g. here is example of mapped names given the order of incoming names:
foo_2
foo
foo -> foo_1
foo -> foo_3 foo_2 was skipped
foo -> foo_4
foo_1 -> foo_1_1 number appended to make unique
this solution copies the index style used by windows, "filename (n).doc", respecting the file extensions
Map<String, Integer> nombresRepeticiones = new HashMap<String, Integer>();
for(FileDTO file : files) {
String filename = file.getNombre();
if (nombresRepeticiones.containsKey(filename)) {
int numeroRepeticiones = nombresRepeticiones.get(filename) + 1;
String base = FilenameUtils.removeExtension(filename);
String extension = FilenameUtils.getExtension(filename);
filename = base + " (" + numeroRepeticiones + ")";
if (extension != null && !extension.isEmpty()) {
filename = filename + "." + extension;
}
nombresRepeticiones.put(file.getNombre(), numeroRepeticiones);
}
else {
nombresRepeticiones.put(filename, 0);
}
ZipEntry ze = new ZipEntry(filename);
zos.putNextEntry(ze);
zos.write(IOUtils.toByteArray(file.getContenido().getInputStream()));
zos.closeEntry();
}

Unzip nested jar files java

I am trying to unzip all the jar files and the jar files which is nested in jar file.
For example, let's say there's a Test.jar and inside of the Test.jar, there is Test1.jar,,
What I tried to do is that making a temp directory and unzip them, when it was jar file, recursive call.
Here below is my code and the log I got. I have no idea on that.
I am pretty sure that the input was directory. I have no idea on resolving this error. Also, I am pretty sure that the error is from here (Collection<File> files = FileUtils.listFiles(root, null, recursive);)
Curr directory:/Users/younghoonkwon/jar-analyzer
unzipping directory/Users/younghoonkwon/jar-analyzer/test1.jar#
Curr directory:/Users/younghoonkwon/jar-analyzer/test1.jar#
java.lang.IllegalArgumentException: Parameter 'directory' is not a directory
at org.apache.commons.io.FileUtils.validateListFilesParameters(FileUtils.java:545)
at org.apache.commons.io.FileUtils.listFiles(FileUtils.java:521)
at org.apache.commons.io.FileUtils.listFiles(FileUtils.java:691)
at org.vulnerability.checker.JarParser.unzipJars(JarParser.java:31)
at org.vulnerability.checker.JarParser.unzipJars(JarParser.java:38)
at org.vulnerability.checker.VulnerabilityChecker.main(VulnerabilityChecker.java:26)
[/Users/younghoonkwon/jar-analyzer/test1.jar]
My code:
public void unzipJars(String toFind, String currDirectory) {
File root = new File(currDirectory);
try {
boolean recursive = true;
System.out.println("Curr directory:"+root);
Collection<File> files = FileUtils.listFiles(root, null, recursive);
for (Iterator<File> iterator = files.iterator(); iterator.hasNext();) {
File file = (File) iterator.next();
if (file.getName().endsWith(toFind)) {
if(toFind.endsWith("jar")) {
unzip(file.getAbsolutePath() + "#",file.getAbsolutePath());
System.out.println("unzipping directory"+ file.getAbsolutePath()+"#");
unzipJars("jar", file.getAbsolutePath()+"#");
this.jarList.add(file.getAbsolutePath());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
static void unzip(String destDirPath, String zipFilePath) throws IOException {
Runtime.getRuntime().exec("unzip "+ zipFilePath + " -d" + destDirPath);
}
The algorithm seems ok to me. The error seems to be caused by that the unzipped file is not a directory (but a file) or it does not exist. Your unzip() method does not throw any exeption if unzipping the .jar fails because of output file already existing.
Have you been running the code earlier which may have caused that the .jars or directories contain unwanted output files with the same name?
Before the call to FileUtils.listFiles(), check if the root File object is actually a directory and it exists (or if it's a file but not a directory) by File.isDirectory() or File.isFile().
The following method decompress() unzips a JAR file and all the JAR files within it (recursively).
/**
* Size of the buffer to read/write data.
*/
private static final int BUFFER_SIZE = 16384;
/**
* Decompress all JAR files located in a given directory.
*
* #param outputDirectory Path to the directory where the decompressed JAR files are located.
*/
public static void decompress(final String outputDirectory) {
File files = new File(outputDirectory);
for (File f : Objects.requireNonNull(files.listFiles())) {
if (f.getName().endsWith(".jar")) {
try {
JarUtils.decompressDependencyFiles(f.getAbsolutePath());
// delete the original dependency jar file
org.apache.commons.io.FileUtils.forceDelete(f);
} catch (IOException e) {
log.warn("Problem decompressing jar file: " + f.getAbsolutePath());
}
}
}
}
/**
* Decompress all JAR files (recursively).
*
* #param zipFile The file to be decompressed.
*/
private static void decompressDependencyFiles(String zipFile) throws IOException {
File file = new File(zipFile);
try (ZipFile zip = new ZipFile(file)) {
String newPath = zipFile.substring(0, zipFile.length() - 4);
new File(newPath).mkdir();
Enumeration<? extends ZipEntry> zipFileEntries = zip.entries();
// Process each entry
while (zipFileEntries.hasMoreElements()) {
// grab a zip file entry
ZipEntry entry = zipFileEntries.nextElement();
String currentEntry = entry.getName();
File destFile = new File(newPath, currentEntry);
File destinationParent = destFile.getParentFile();
// create the parent directory structure if needed
destinationParent.mkdirs();
if (!entry.isDirectory()) {
BufferedInputStream is = new BufferedInputStream(zip.getInputStream(entry));
int currentByte;
// establish buffer for writing file
byte[] data = new byte[BUFFER_SIZE];
// write the current file to disk
FileOutputStream fos = new FileOutputStream(destFile);
try (BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER_SIZE)) {
// read and write until last byte is encountered
while ((currentByte = is.read(data, 0, BUFFER_SIZE)) != -1) {
dest.write(data, 0, currentByte);
}
dest.flush();
is.close();
}
}
if (currentEntry.endsWith(".jar")) {
// found a zip file, try to open
decompressDependencyFiles(destFile.getAbsolutePath());
FileUtils.forceDelete(new File(destFile.getAbsolutePath()));
}
}
}
}

How to get the whole file structure as a tree when there are jar files in this jar file

I want to get the whole file sturcture of a jar file as a tree. I find many solutions. I am deploy it as a zip file. I followed the link How to get names of classes inside a jar file?
Code looks as follow:
public void getClassFromJar(String path) throws IOException {
//ArrayList<String> classNames=new ArrayList<String>();
ZipInputStream zip=new ZipInputStream(new FileInputStream(path));
IntoEntry(zip);
//return classNames;
}
public void IntoEntry(ZipInputStream zip) throws IOException {
for(ZipEntry entry=zip.getNextEntry();entry!=null;entry=zip.getNextEntry()) {
System.out.println("entry: "+entry.getName());
if (entry.getName().endsWith(".jar")) {
// How to do
}
if(entry.getName().endsWith(".class") && !entry.isDirectory()) {
// This ZipEntry represents a class. Now, what class does it represent?
StringBuilder className=new StringBuilder();
for(String part : entry.getName().split("/")) {
if(className.length() != 0) {
className.append(".");
}
className.append(part);
if(part.endsWith(".class")) {
className.setLength(className.length()-".class".length());
}
}
classNames.add(className.toString());
}
}
}
The result from D:\work\workspace\myjar\org.objectweb.asm_2.2.2.jar(It is not in classpath.) print by System.out.println("entry: "+entry.getName());:
entry: output/
entry: output/dist/
entry: output/dist/lib/
entry: output/dist/lib/asm-2.2.2.jar
entry: output/dist/lib/asm-analysis-2.2.2.jar
entry: output/dist/lib/asm-attrs-2.2.2.jar
entry: output/dist/lib/asm-commons-2.2.2.jar
entry: output/dist/lib/asm-tree-2.2.2.jar
entry: output/dist/lib/asm-util-2.2.2.jar
entry: plugin.xml
How to go into the jar files in this jar file?
You can try:
public static void printJarContent(File jarFile) {
java.util.jar.JarFile jar = new java.util.jar.JarFile(jarFile);
java.util.Enumeration enum = jar.entries();
while (enum.hasMoreElements()) {
java.util.jar.JarEntry file = (java.util.jar.JarEntry) enum.nextElement();
// temp directory where the jar will be extracted
java.io.File f = new java.io.File(DEST_DIR + java.io.File.separator + file.getName());
String ext = Files.probeContentType(f.toPath());
if(ext.equalsIgnoreCase("jar")) {
// extract current nested jar to a DEST_DIR and then
printJarContent(f);
}
java.io.InputStream is = jar.getInputStream(file); // get the input stream
while (is.available() > 0) {
//print out the (is.read()) or do whatever you want with it
}
is.close();
}

checking if file exists in a specific directory

I am trying to check for a specific file in a given directory. I don't want the code but I want to fix the one I have. The only difference in this question, is that I look for files with an extension .MOD.
I have the code ready:-
public static int checkExists(String directory, String file) {
File dir = new File(directory);
File[] dir_contents = dir.listFiles();
String temp = file + ".MOD";
boolean check = new File(temp).exists();
System.out.println("Check"+check); // -->always says false
for(int i = 0; i<dir_contents.length;i++) {
if(dir_contents[i].getName() == (file + ".MOD"))
return Constants.FILE_EXISTS;
}
return Constants.FILE_DOES_NOT_EXIST;
}
But for some reasons, it does not work. I don't understand why, can anybody find any bug here?
Do you expect temp.MOD file to be in the current directory (the directory from which you run your application), or you want it to be in the "directory" folder? In the latter case, try creating the file this way:
boolean check = new File(directory, temp).exists();
Also check for the file permissions, because it will fail on permission errors as well. Case sensitivily might also be the cause of the issue as Spaeth mentioned.
This is where you have the bug.
String temp = file + ".MOD";
And
if(dir_contents[i].getName() == (file + ".MOD"))
The code boolean check = new File(temp).exists(); will check for the file in the current directory not in the required directory.
String dirName="/home/demo";
File dir = new File(dirName);
File[] dir_contents = dir.listFiles();
String temp = dirName+"/"+"README" + ".MOD";
boolean check = new File(temp).exists();
System.out.println("Check" + check); // -->always says false
for (int i = 0; i < dir_contents.length; i++) {
if (dir_contents[i].getName().equals("README" + ".MOD"))
return Constants.FILE_EXISTS;
}
return Constants.FILE_DOES_NOT_EXIST;
Try this..............
File f = new File("./file_name");
if(f.exists()){
System.out.println("success");
}
else{
System.out.println("fail");
}

Categories

Resources