I have a list of files from different locations. I create a zip file using the following the code which works without error. But when I try to unzip the file in Windows using Extract All it fails seeing unable to find any bytes, yet if I double click into the zip file itself with Windows Explorer I can see the files and individual ones can be opened and contains the correct data
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile));
for (File next : files)
{
ZipEntry zipEntry = new ZipEntry(next.getName());
zos.putNextEntry(zipEntry);
FileInputStream in = new FileInputStream(next);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0)
{
zos.write(buf, 0, len);
}
zos.closeEntry();
in.close();
}
zos.close();
This may or may not be related but I've found using fixed byte length can lead to a loss of new line characters.
This may help:
final byte[] newLine = System.getProperty(
"line.separator").getBytes("UTF-8");
while ((line = in.readLine()) != null)
final byte[] buffer = line.getBytes("UTF-8");
out.write(buffer, 0, buffer.length);
out.write(newLine, 0, newLine.length);
}
Related
I´m trying to implement some "over the air" update mechanism for OSGi bundles. For that, I need to be able to create a jar file from a String (basically the content of the jar file read by JarInputStream). The following example code should illustrate my needs:
//read bundle to be copied!
File originalFile = new File(
"/Users/stefan/Documents/Projects/OSGi/SimpleBundle_1.0.0.201404.jar");
JarInputStream fis = new JarInputStream(new FileInputStream(originalFile));
StringBuilder stringBuilder = new StringBuilder();
int ch;
while ((ch = fis.read()) != -1) {
stringBuilder.append((char) ch);
}
fis.close();
//Create content string
String content = stringBuilder.toString();
if (logger.isInfoEnabled()) {
logger.info(content);
}
//Init new jar input stream
JarInputStream jarInputStream = new JarInputStream(
new ByteArrayInputStream(content.getBytes()));
if (logger.isInfoEnabled()) {
logger.info("Save content to disc!");
}
File newFile = new File(
"/Users/stefan/Documents/Projects/OSGi/equinox/SimpleBundle_1.0.0.201404.jar");
//Init new jar output stream
JarOutputStream fos = new JarOutputStream(
new FileOutputStream(newFile));
if (!newFile.exists()) {
newFile.createNewFile();
}
int BUFFER_SIZE = 10240;
byte buffer[] = new byte[BUFFER_SIZE];
while (true) {
int nRead = jarInputStream.read(buffer, 0,
buffer.length);
if (nRead <= 0)
break;
fos.write(buffer, 0, nRead);
}
//Write content to new jar file.
fos.flush();
fos.close();
jarInputStream.close();
Unfortunately, the created jar file is empty and throws an "Invalid input file" error if I try to open it with JD-GUI. Is it possible to create a jar file from the String "content"?
Best regards and thank you very much
Stefan
Your jar is empty because you do not read anything from the JarInputStream. If you want to read JarInputStream, you should iterate its entries. If you want to change the Manifest, the first entry should be skipped, use the getManifest() of the jarInputStream and the constructor of the JarOutputStream, where Manifest can be specified. Based on your code (no manifest change but plain jar copy):
ZipEntry zipEntry = jarInputStream.getNextEntry();
while (zipEntry != null) {
fos.putNextEntry(zipEntry);
// Simple stream copy comes here
int BUFFER_SIZE = 10240;
byte buffer[] = new byte[BUFFER_SIZE];
int l = jarInputStream.read(buffer);
while(l >= 0) {
fos.write(buffer, 0, l);
l = jarInputStream.read(buffer);
}
zipEntry = jarInputStream.getNextEntry();
}
You only need this if you want to change the content (Manifest or entries) of the JAR file during the copy. Otherwise, simple InputStream and FileOutputStream will do the work (as Tim said).
When I zip files using 64 bit Java, the zip file show up as empty on Windows 7. Is there a way to force 32 bit version of zip using 64 bit Java?
EDIT:
I'm able to open/unzip it using third party tools like BeyondCompare. When I browse that file through Windows 7, the content is empty. Unzipping it using Win 7 gives me 'Invalid zip file' error.
public static void zipFiles(Collection<String> fileLocations, String targetZipFile){
if( fileLocations == null || fileLocations.size() <= 0 ){
return;
}
byte[] buffer = new byte[1024];
try{
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(targetZipFile));
FileInputStream in = null;
String fileName = null;
for( String fileLoc : fileLocations ){
fileName = fileLoc.substring(fileLoc.lastIndexOf(File.separator));
// Add ZIP entry to output stream.
out.putNextEntry(new ZipEntry(fileName));
in = new FileInputStream(fileLoc);
int len;
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
// Complete the entry
out.closeEntry();
in.close();
}
// Complete the ZIP file
out.close();
}catch(IOException ioe){
LOGGER.error(ioe.getMessage(),ioe);
}
}
I'm creating a xlsx using poi and saving it on fileSystem. I need to download the file on a servlet call and due to memory constraints I did not create a xssf workbook object and used the following code instead :
byte[] buf = new byte[1024];
ServletOutputStream sOut = response.getOutputStream();
FileInputStream input = null;
try {
long length = fileToRead.length();
input = new FileInputStream(fileToRead);
while ((input != null) && ((length = input.read(buf)) != -1)) {
sOut.write(buf, 0, (int) length);
}
Where fileToRead is the file present at the file system.
How can I integrate this with How to create a zip file in Java
You could use
ZipOutputStream zos = new ZipOutputStream(response.getOutputStream());
....
ze = new ZipEntry("xlsData");
zos.putEntry (ze);
// loop
zos.write(buf, 0, (int) length);
// finally
zos.close();
When I'm writing entries into a zip file like this:
ZipEntry ze = zin.getNextEntry();
while (ze != null) {
InputStream is = zf.getInputStream(ze);
zos.putNextEntry(ze);
int len;
while ((len = is.read(buffer)) >= 0) {
zos.write(buffer, 0, len);
}
zos.closeEntry();
ze = zin.getNextEntry();
}
I get the following exception on the second while loop:
java.util.zip.ZipException: invalid code lengths set
at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:164)
at java.io.FilterInputStream.read(FilterInputStream.java:107)
Anybody knows why this exception is thrown and what does it mean?
P.S. I should mention that I'm running this on a listeners on JBoss 7.1.1 in order to zip vaious log files from different folders. There's a thread for each folder. Could the fact of using multiple threads lead to this problem?
You are setting the ZipEntry of the new zip file to the same instance you got from the original file. This implies that all values must match, but this fails if the compressed size of the written entry does not match the compressed size of the source file. And the tiniest bit of difference between the original compression code and the one you are using now will yield to different compressed sizes. To make it run you have to create a copy of the ZipEntry for the output and reset the compressed size on it.
By the way, you are using zin.getNextEntry() and zf.getInputStream(ze) in your code which implies that you are using a ZipFile and a ZipInputStream at the same time. If they refer to the same file, it’s a waste of resources, if they refer to different files, you can expect even more problems.
Decide for either ZipFile
ZipFile zf = …
ZipOutputStream zos = …
byte[] buffer = …
for(Enumeration<? extends ZipEntry> e=zf.entries(); e.hasMoreElements();) {
ZipEntry ze = e.nextElement();
InputStream is = zf.getInputStream(ze);
ZipEntry zeOut=new ZipEntry(ze);
zeOut.setCompressedSize(-1);
zos.putNextEntry(zeOut);
int len;
while ((len = is.read(buffer)) >= 0) {
zos.write(buffer, 0, len);
}
zos.closeEntry();
}
zos.close();
zf.close();
or ZipInputStream
ZipInputStream zin…
ZipOutputStream zos=…
byte[] buffer = …
ZipEntry ze = zin.getNextEntry();
while (ze != null) {
ZipEntry zeOut=new ZipEntry(ze);
zeOut.setCompressedSize(-1);
zos.putNextEntry(zeOut);
int len;
while ((len = zin.read(buffer)) >= 0) {
zos.write(buffer, 0, len);
}
zos.closeEntry();
ze = zin.getNextEntry();
}
zos.close();
zin.close();
I'm trying to write inputstream to a file, but it never gets written on disk, I just get the error file doesnt exist. The file I open is a drawable icluded in the project, I would like to save it to sd card. This is what I have so far:
File storagePath = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/tester");
InputStream inputStream = getResources().openRawResource(R.drawable.test);
OutputStream out = new FileOutputStream(new File(storagePath, "test.png"));
byte buffer[] = new byte[900];
int len;
while ((len = inputStream.read(buf)) > 0)
out.write(buffer, 0, len);
out.close();
inputStream.close();
Your tester directory doesn't exist. Check for it and create it if necessary before opening your FileOutputStream.