producing an empty zip file java - java

I'm currently writing a function what would create a zip file, which will be used in other functionality. Below it is my function's code:
public void createZip(){
try{
String outfile = this.filename + ".zip";
//input file
FileInputStream input = new FileInputStream(this.filename);
//output file
ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(outfile));
//name the file inside the zip file
System.out.println(this.filename);
zip.putNextEntry(new ZipEntry(this.filename));
byte[] buffer = new byte[this.BUFFER];
int len;
//copy the file to the zip
while((len= input.read(buffer)) > 0){
System.out.println(len);
zip.write(buffer, 0, len);
}
zip.closeEntry();
zip.flush();
input.close();
zip.close();
this.filename += ".zip";
}
catch(IOException e){
e.printStackTrace();
}
}
I have tried to debug, but I couldn't find the source of this problem. The function runs without any further problems, but the zip file produced it is an empty one.

You must close the entry using ZipOutputStream#closeEntry() prior to closing the output stream, or the entry is never confirmed to have been written entirely.
Also, the name of the ZipEntry cannot be the entire path; i.e, it should be dog.png instead of C:\Users\Admin\Documents\dog.png. This issue will pass by without an exception, and will cause the data from the file to be compressed directly into the zip, rather than into the zip as a compressed file.

final static byte[] EmptyZip={80,75,05,06,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00};
public static void createEmptyZip(String path){
try{
FileOutputStream fos=new FileOutputStream(new File(path));
fos.write(EmptyZip, 0, 22);
fos.flush();
fos.close();
}catch (FileNotFoundException e){
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

well, just wondering why you pass a filename as a parameter if you dont use it within the code..
Since you are always using the this.filename. That makes me think that you are trying to name a zip file with a name you set into the objects state and since you are also using that same name in the ZipEntry its trying to add that same zipper file inside it.. since the ZipEntry must point to an existing file, thats why it comes up empty.
Hope it helps.

Try to flush the buffer by using zip.flush() before closing, although close should flush the buffer.
Also verify this.filename. You have a local variable with the same name. The local variable filename is never used. It's possible the zip file is being written to a different location than what you expect.

#phillipe try this please
public void createZip(String filename) {
try {
//input file
FileInputStream input = new FileInputStream(filename);
//output file
ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(filename + ".zip"));
//name the file inside the zip file
zip.putNextEntry(new ZipEntry(filename));
byte[] buffer = new byte[1024];
int len;
//copy the file to the zip
while((len = input.read(buffer)) > 0) {
System.out.println();
zip.write(buffer, 0 , len);
}
zip.closeEntry();
zip.flush();
zip.close();
input.close();
filename += ".zip";
} catch(IOException e) {
e.printStackTrace();
}
}
those code create a zip file and that's work and for me too. :)

Simple solution. Make one manual directory in ZipEntry without File Separator.
zip.putNextEntry(new ZipEntry("LOG" + fileName));
instead of
zip.putNextEntry(new ZipEntry(fileName));
Here fileName = file.getAbsoluteFile();
This will first create LOG dir in zip file followed by fileNames with directory path. This avoids creating initial empty directory in zip file.

Related

How to read a binary file, modify the same file and save the file with the modifications?

I am currently working a project and we have divided it in modules, in one of them, we have a file ( .exe ) extension. I decided to open it in binary format and read the contents of it, modify them. But, I am not to modify the changes and save it in the same file. When I am trying to do so, it says 0KB. It's working perfectly fine when using two files.
Here is the source code :
public static void main(String[] args) {
String strSourceFile="E:/e.exe";
String strDestinationFile="E:/f.exe";
try
{
FileInputStream fin = new FileInputStream(strSourceFile);
FileOutputStream fout = new FileOutputStream(strDestinationFile);
byte[] b = new byte[1];
int noOfBytes = 0;
System.out.println("Copying file using streams");
while( (noOfBytes = fin.read(b)) != -1 )
{
fout.write(b, 0, noOfBytes);
}
System.out.println("File copied!");
//close the streams
fin.close();
fout.close();
Use RandomAccessFile or You can also create a new file with your changes save it and delete the original one. Once original file is deleted then rename this new file to the original one.
You are trying to read and write the same file with the input and the output stream so the file is not getting copied while you try to do it with the same file. Instead, use a middle file as the buffer, as in the below code I have used the f.exe as the middle buffer, next I have copied the data from the buffer file again to the original file jar.exe, at last you need to delete the buffer file.
Here is the below code :
String strSourceFile = "C:/jar.exe";
String strDestinationFile = "C:/f.exe";
FileInputStream fin = new FileInputStream(strSourceFile);
FileOutputStream fout = new FileOutputStream(strDestinationFile);
byte[] b = new byte[1];
int noOfBytes = 0;
System.out.println("Copying file using streams");
while ((noOfBytes = fin.read(b)) != -1) {
fout.write(b, 0, noOfBytes);
}
fin.close();
fout.close();
String strDestinationFile1 = "C:/jar.exe";
FileInputStream fin1 = new FileInputStream(strDestinationFile);
FileOutputStream fout1 = new FileOutputStream(strDestinationFile1);
while ((noOfBytes = fin1.read(b)) != -1) {
fout1.write(b, 0, noOfBytes);
}
System.out.println("File copied!");
//close the streams
fin1.close();
fout1.close();
File file = new File("C:/f.exe");
file.delete();

File reader deletes the contet of a file

I'm writing a java server and always read requests form the browser. For example, I have in browser http://localhost:8080/C:\Users\1\Desktop\tur.txt and read this request. Then saves a file path. Then I want to print the contents of the file to browser. For example, some text which is in tur.txt.
I'm doing it with a method in another class.
Here is a code of this class:
public class FileReader {
BufferedReader in;
File DataFile;
public void Reader(String directory, PrintStream out) throws IOException {
try {
File stockInputFile = new File(directory);
File StockOutputFile = new File(directory);
FileInputStream fis = new FileInputStream(stockInputFile);
FileOutputStream fos = new FileOutputStream(StockOutputFile);
int count;
if (new File(directory).isDirectory()) {
directory=directory.replace('\\', '/');
out.print("HTTP/1.0 301 Moved Permanently\r\n"+
"Location: /"+directory+"/\r\n\r\n");
out.close();
return;
}
// Open the file (may throw FileNotFoundException)
InputStream f=new FileInputStream(directory);
// Determine the MIME type and print HTTP header
String mimeType="text/plain";
if (directory.endsWith(".html") || directory.endsWith(".htm"))
mimeType="text/html";
else if (directory.endsWith(".jpg") || directory.endsWith(".jpeg"))
mimeType="image/jpeg";
else if (directory.endsWith(".gif"))
mimeType="image/gif";
else if (directory.endsWith(".txt"))
mimeType="text/txt";
else if (directory.endsWith(".class"))
mimeType="application/octet-stream";
out.print("HTTP/1.0 200 OK\r\n"+
"Content-type: "+mimeType+"\r\n\r\n");
System.out.println(mimeType);
// Send file contents to client, then close the connection
byte[] a=new byte[4096];
int n;
while ((n=f.read(a))>0)
out.write(a, 0, n);
// out.flush();
out.close();
}
catch (FileNotFoundException x) {
out.println("HTTP/1.0 404 Not Found\r\n"+
"Content-type: text/html\r\n\r\n"+
"<html><head></head><body>"+directory+" not found</body></html>\n");
out.close();
}
}
}
It takes a directory to find a file a file on disk and PrintStream (PrintStream out = new PrintStream(new BufferedOutputStream(serSock.getOutputStream()));) to print the content to browser. But, the problem is that when I read this file. The content of this file removes. That means all that text that I had in tur.txt deletes. And the file becomes emtpty intead of beeng printed to the browser.
Can anyone explain why? Thank you.
The problem was here:
FileInputStream fis = new FileInputStream(stockInputFile);
FileOutputStream fos = new FileOutputStream(StockOutputFile);
In FileOutputSteam. So when I deleted these 2 lines the program started to work correctly. I forgot that FileOutputStream clears all the data stored in the file.
I would like to thank #lamsomeone for his help.

Extracting zip file into a folder throws "Invalid entry size (expected 46284 but got 46285 bytes)" for one of the entry

When I am trying to extract the zip file into a folder as per the below code, for one of the entry (A text File) getting an error as "Invalid entry size (expected 46284 but got 46285 bytes)" and my extraction is stopping abruptly. My zip file contains around 12 text files and 20 TIF files. It is encountering the problem for the text file and is not able to proceed further as it is coming into the Catch block.
I face this problem only in Production Server which is running on Unix and there is no problem with the other servers(Dev, Test, UAT).
We are getting the zip into the servers path through an external team who does the file transfer and then my code starts working to extract the zip file.
...
int BUFFER = 2048;
java.io.BufferedOutputStream dest = null;
String ZipExtractDir = "/y34/ToBeProcessed/";
java.io.File MyDirectory = new java.io.File(ZipExtractDir);
MyDirectory.mkdir();
ZipFilePath = "/y34/work_ZipResults/Test.zip";
// Creating fileinputstream for zip file
java.io.FileInputStream fis = new java.io.FileInputStream(ZipFilePath);
// Creating zipinputstream for using fileinputstream
java.util.zip.ZipInputStream zis = new java.util.zip.ZipInputStream(new java.io.BufferedInputStream(fis));
java.util.zip.ZipEntry entry;
while ((entry = zis.getNextEntry()) != null)
{
int count;
byte data[] = new byte[BUFFER];
java.io.File f = new java.io.File(ZipExtractDir + "/" + entry.getName());
// write the files to the directory created above
java.io.FileOutputStream fos = new java.io.FileOutputStream(ZipExtractDir + "/" + entry.getName());
dest = new java.io.BufferedOutputStream(fos, BUFFER);
while ((count = zis.read(data, 0, BUFFER)) != -1)
{
dest.write(data, 0, count);
}
dest.flush();
dest.close();
}
zis.close();
zis.closeEntry();
}
catch (Exception Ex)
{
System.Out.Println("Exception in \"ExtractZIPFiles\"---- " + Ex.getMessage());
}
I can't understand the problem you're meeting, but here is the method I use to unzip an archive:
public static void unzip(File zip, File extractTo) throws IOException {
ZipFile archive = new ZipFile(zip);
Enumeration<? extends ZipEntry> e = archive.entries();
while (e.hasMoreElements()) {
ZipEntry entry = e.nextElement();
File file = new File(extractTo, entry.getName());
if (entry.isDirectory()) {
file.mkdirs();
} else {
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
InputStream in = archive.getInputStream(entry);
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
IOUtils.copy(in, out);
in.close();
out.close();
}
}
}
Calling:
File zip = new File("/path/to/my/file.zip");
File extractTo = new File("/path/to/my/destination/folder");
unzip(zip, extractTo);
I never met any issue with the code above, so I hope that could help you.
Off the top of my head, I could think of these reasons:
There could be problem with the encoding of the text file.
The file needs to be read/transferred in "binary" mode.
There could be an issue with the line ending \n or \r\n
The file could simply be corrupt. Try opening the file with a zip utility.

How does one go about finding a specific directory out of a jar/zip file in java?

I have been working on this for quite a few hours. I can't seem to find the issue to this problem. Essentially what I have is this:
I have a jar, let's call it "a.jar"
I need to get the directory "z" and it's contents from "a.jar", but "z" isn't in the root directory of "a.jar".
"z" is in "/x/y/" and "/x/y/" is in "a.jar", so it looks like this:
"a.jar/x/y/z/"
I hope that's a decent explanation. By the way, "a.jar" is what everything is running out of, so its in the class path obviously.
Basically for each ZipEntry you have to check if it isDirectory() and parse that also.
Checkout this link:
http://www.javaworld.com/javaworld/javatips/jw-javatip49.html
LE:
Here is a complete example that extracts the files from the jar, and if you specify a specific path it will extract only that folder:
public void doUnzip(String inputZip, String destinationDirectory, String specificPath)
throws IOException {
int BUFFER = 2048;
File sourceZipFile = new File(inputZip);
File unzipDestinationDirectory = new File(destinationDirectory);
unzipDestinationDirectory.mkdir();
ZipFile zipFile;
// Open Zip file for reading
zipFile = new ZipFile(sourceZipFile, ZipFile.OPEN_READ);
// Create an enumeration of the entries in the zip file
Enumeration<?> zipFileEntries = zipFile.entries();
// Process each entry
while (zipFileEntries.hasMoreElements()) {
// grab a zip file entry
ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
if(specificPath != null){
if(entry.getName().startsWith(specificPath) == false)
continue;
}
File destFile = new File(unzipDestinationDirectory, entry.getName());
// create the parent directory structure if needed
destFile.getParentFile().mkdirs();
try {
// extract file if not a directory
if (!entry.isDirectory()) {
BufferedInputStream is = new BufferedInputStream(
zipFile.getInputStream(entry));
// establish buffer for writing file
byte data[] = new byte[BUFFER];
// write the current file to disk
FileOutputStream fos = new FileOutputStream(destFile);
BufferedOutputStream dest = new BufferedOutputStream(fos,
BUFFER);
// read and write until last byte is encountered
for (int bytesRead; (bytesRead = is.read(data, 0, BUFFER)) != -1;) {
dest.write(data, 0, bytesRead);
}
dest.flush();
dest.close();
is.close();
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
zipFile.close();
}
public static void main(String[] args) {
Unzip unzip = new Unzip();
try {
unzip.doUnzip("test.jar", "output", "x/y/z");
} catch (IOException e) {
e.printStackTrace();
}
}
..(ZipEntry), but they don't work very well with sub-directories.
They work just fine. Iterate the entries and simply check the path equates to that sub-directory. If it does, add it to a list (or process it, whatever).

Java - copy Jar Folder

Actually I am confronted with a Problem. I've got a ".apk-File" in one Package of my Application. apk is a kind of a jar File (apk = Android Package).
I now want to copy this jar-file out of my Programm onto any other Location at the PC.
Normally I would do this by using:
FileInputStream is = new FileInputStream(this.getClass().getResource("/resources/myApp.apk").getFile());
And then write it on the disk with using a FileOutputStream.
... but since an .apk is a kind of a .jar it doesn't work. It just copies the .apk file. but without the containing other files.
any help would be appreciated
Since .apk is a .jar file by another name (in other words it is a zip file with some specific definitions of where configuration files are stored inside the directory) then look at ZipInputStream to read the file and walk through the contents and write them out as files.
Thank you very much Yishai... this was the Hint I was waiting for :)
Probably is sb out there, who needs the to do a same thing, therefore... here is my code:
public static boolean copyApkFile(File outputFile){
try {
FileInputStream fis = new FileInputStream(this.getClass().getResource("/resources/myApkFile.apk").getFile());
ZipInputStream zis = new ZipInputStream(fis);
FileOutputStream fos = new FileOutputStream(outputFile));
ZipOutputStream zos = new ZipOutputStream(fos);
ZipEntry ze = null;
byte[] buf = new byte[1024];
while ((ze = zis.getNextEntry()) != null) {
System.out.println("Next entry "+ze.getName()+" "+ze.getSize());
zos.putNextEntry(ze);
int len;
while ((len = zis.read(buf)) > 0) {
zos.write(buf, 0, len);
}
}
zos.close();
fos.close();
zis.close();
fis.close();
return true;
} catch (IOException ex) {
Logger.getLogger(SetUpNewDevice.class.getName()).log(Level.SEVERE, null, ex);
return false;
}
}

Categories

Resources