Whats wrong with this zip method? - java

I have a method which zips up 5 files. It produces a zip file without error, but I cannot open it to examine the contents. I tried emailing it and gmail said it cannot send corrupt files. Trying to open with WinRAR in Windows results in an error stating:
The archive is either in unknown format or damaged
This is the method:
private void zipTestFiles() throws FileNotFoundException, IOException
{
File[] filenames = fileDir.listFiles(fileNameFilter(Constants.PAGE_MON_FILENAME_FILTER));
byte[] buf = new byte[1024];
String outFilename = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separatorChar + Constants.PAGEMONITOR_ZIP;
DeflaterOutputStream out = new DeflaterOutputStream(new BufferedOutputStream(new FileOutputStream(outFilename)));
for (int i=0; i<filenames.length; i++)
{
FileInputStream in = new FileInputStream(filenames[i]);
int len;
while ((len = in.read(buf)) > 0)
{
out.write(buf, 0, len);
}
in.close();
}
out.close();
}

You should use ZipOutputStream instead of DeflaterOutputStream. And do not forget to create entries. Read javadoc of ZipOutputStream before writing the implementation.

Try with ZipOutputStream which already exists in Java. DeflaterOutputStream only uses DEFLATE method to compress but doesn't put ZIP headers automatically.

Related

Unable to compress a CSV file Java

I'm trying to convert an existing CSV file to a gzip file.
I verified the CSV looks good. Once I run this code, I get a "failed to expand" error and tried an online decompression tool that also failed, so it seems the output zip is corrupt.
public void compressGzip(String input, String dest) throws IOException {
Path pathSource = Paths.get(input);
Path destSource = Paths.get(dest);
try (GZIPOutputStream gos = new GZIPOutputStream(
new FileOutputStream(destSource.toFile()));
FileInputStream fis = new FileInputStream(pathSource.toFile())) {
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) > 0) {
gos.write(buffer, 0, len);
}
}
}
Anything I could be missing here?

Zip multipartfile and store via FTP

I take a multipartfile (i.e. SAMPLE.csv) in input.
I should zip it (i.e. SAMPLE.zip) and store it via FTP.
public void zipAndStore(MultipartFile file) {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
InputStream is = file.getInputStream()) {
ZipEntry zipEntry = new ZipEntry("SAMPLE.zip");
zos.putNextEntry(zipEntry);
byte[] bytes = new byte[1024];
int length;
while ((length = is.read(bytes)) >= 0) {
zos.write(bytes, 0, length);
}
zos.closeEntry();
storeFtp("SAMPLE.zip", new ByteArrayInputStream(baos.toByteArray()));
} catch (Exception e) {
}
}
The storeFtp use the org.apache.commons.net.ftp.FTPClient.storeFile(String remote, InputStream local) method.
The problem is that the uploaded file is corrupted and i'm unable to manually decompress.
What's wrong?
A zipfile has a list of DirEntries and a endLocator at the end of the file (after all the ZipFileRecords, i.e. the ZipEntries in the code).
So you probably have to close the zipfile before calling storeFtp() to make sure the DirEntries and the endLocator are written to the file:
zos.closeEntry();
zos.close();
storeFtp("SAMPLE.zip", new ByteArrayInputStream(baos.toByteArray()));
(I don't know Java that well, so I can't check or test the full code)
Also check out this answer.

making zip process more optimized one

I have developed a method to zip a file that will take file path and filename as a parameter and will zip a file as shown below could you please advise how can I modify this method to be more efficient and more fast as I am a big fan of optimization..
public File generateZipForAFile(String folderPath, String reportFileName)
throws FileNotFoundException, IOException {
File inputFile = new File(folderPath + reportFileName);
FileInputStream in = new FileInputStream(inputFile);
File outputZipFile = new File(folderPath, reportFileName + ".zip");
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(outputZipFile));
// Add ZIP entry to output stream.
out.putNextEntry(new ZipEntry(reportFileName ));
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
out.closeEntry();
out.close();
in.close();
return outputZipFile;
}
There is not much you can do in your code. Furthermore, most of the time is spent while actually doing the zip.
So even if you reduce the time spent in your part to 0 the overall gain will be very small.

Zipping Files using util.zip No directory

I have the following situation:
I am able to zip my files with the following method:
public boolean generateZip(){
byte[] application = new byte[100000];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// These are the files to include in the ZIP file
String[] filenames = new String[]{"/subdirectory/index.html", "/subdirectory/webindex.html"};
// Create a buffer for reading the files
try {
// Create the ZIP file
ZipOutputStream out = new ZipOutputStream(baos);
// Compress the files
for (int i=0; i<filenames.length; i++) {
byte[] filedata = VirtualFile.fromRelativePath(filenames[i]).content();
ByteArrayInputStream in = new ByteArrayInputStream(filedata);
// Add ZIP entry to output stream.
out.putNextEntry(new ZipEntry(filenames[i]));
// Transfer bytes from the file to the ZIP file
int len;
while ((len = in.read(application)) > 0) {
out.write(application, 0, len);
}
// Complete the entry
out.closeEntry();
in.close();
}
// Complete the ZIP file
out.close();
} catch (IOException e) {
System.out.println("There was an error generating ZIP.");
e.printStackTrace();
}
downloadzip(baos.toByteArray());
}
This works perfectly and I can download the xy.zip which contains the following directory and file structure:
subdirectory/
----index.html
----webindex.html
My aim is to completely leave out the subdirectory and the zip should only contain the two files. Is there any way to achieve this?
(I am using Java on Google App Engine).
Thanks in advance
If you are sure the files contained in the filenames array are unique if you leave out the directory, change your line for constructing ZipEntrys:
String zipEntryName = new File(filenames[i]).getName();
out.putNextEntry(new ZipEntry(zipEntryName));
This uses java.io.File#getName()
You can use Apache Commons io to list all your files, then read them to an InputStream
Replace the line below
String[] filenames = new String[]{"/subdirectory/index.html", "/subdirectory/webindex.html"}
with the following
Collection<File> files = FileUtils.listFiles(new File("/subdirectory"), new String[]{"html"}, true);
for (File file : files)
{
FileInputStream fileStream = new FileInputStream(file);
byte[] filedata = IOUtils.toByteArray(fileStream);
//From here you can proceed with your zipping.
}
Let me know if you have issues.
You could use the isDirectory() method on VirtualFile

Java Compress Large File

I'm working on an app that works with some very large files each are around 180mb and there are 3 of them. I would like to add an option to my app to back these files up by compressing them in a zip or a tar or something. What is the best option would be to compress them down as much as possible in Java? Tar? Zip? Gzip?
You can do this programmatically using Apache Compress.
Alright went with zip here is the method i used. I found it online and modded it to junk the path and then just raised the buffer a little got about 450mbs of data down to 100mbs so not to bad :) thanks for the help
public void zipper(String[] filenames, String zipfile){
byte[] buf = new byte[2048];
try {
String outFilename = zipfile;
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(outFilename));
for (int i=0; i<filenames.length; i++) {
FileInputStream in = new FileInputStream(filenames[i]);
File file = new File(filenames[i]);
out.putNextEntry(new ZipEntry(file.getName()));
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
out.closeEntry();
in.close();
}
out.close();
} catch (IOException e) {
}
}
Plus 1 to both of you :)

Categories