Unable to read files from ZIP file input stream - java

I have a Zip file that I am trying to read. I do not want to use a ZipFile because in the future, I would like to do this for data that is not from a file.
This is what I have tried so far. Instead of printing the contents of res00000.dat, it prints an empty line. I do not know how to fix this
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
ZipEntry zipEntry;
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
if (!zipEntry.getName().equals("res00000.dat")) {
zipInputStream.closeEntry();
continue;
}
}
int len;
ByteArrayOutputStream byteArrayOutputStream = new ByterrayOutputStream();
byte[] buffer = new byte[1024];
while ((len = zipInputStream.read(buffer)) > 0) {
byteArrayOutputStream.write(buffer, 0, len);
}
String xml = byteArrayOutputStream.toString();
System.out.println(xml);
zipInputStream.closeEntry();
zipInputStream.close();
return null;
My ZIP file has only two files in it. It is a Blackboard Test bank file that I'm attempting to parse:
Zip file
+-imsmanifest.xml
+-res00000.dat
Can someone please help?

You code currently doesn't handle a missing entry. It just silently scrolls to the end of a ZipInputStream so there is no way to tell what's happening. You could do following to get exception when an entry identified by name is missing:
public String readEntry(ZipInputStream in, String name) {
while ((zipEntry = in.getNextEntry()) != null) {
if (zipEntry.getName().equals(name)) {
return readXml(zipInputStream);
}
}
throw new IllegalStateException(name + " not found inside ZIP");
}
You will most likely observe above IllegalStateException now for missing res00000.dat.
Do note that there is no reason to call closeEntry() manually when scrolling the ZipInputStream as getNextEntry() already does it under the hood. From JDK 11 source code:
public ZipEntry getNextEntry() throws IOException {
ensureOpen();
if (entry != null) {
closeEntry();
}
...

Related

Why does my program skip files when unzipping by java.util.zip?

I read quite a few articles, but I did not find a similar problem and its solution.
I'm try to read all files and some skipped with method zis.getNextEntry
public static void main(String[] args) throws Exception {
String fileZip = "src/main/resources/unzipTest/fias_xml.zip";
ZipInputStream zis = new ZipInputStream(new FileInputStream(fileZip));
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
System.out.println(entry.getName());
}
}
}
But if you unzip with WinRar, for example, everything will be unzipped correctly
Archive files
After running the program
Or how i can see why some files doesn't read?
Can the archive be broken?
After I unzipped and re-zipped the files by using winrar, the program worked correctly. Why was winrar able to do this, but the java code was not?
zipArchive
jdk1.8.0_161
Based on the test i did i able to print each directory and file name correctly.
There 2 scenario came to my mind:
i) the filename length or the complete length is more what the platform can handle. But this also should be same case while do unzip from winrar
ii) Was there any permission issue, but again it won't be selective manner.
can you please let me which jdk version ?
Will u be able to sent me the zip file, I can try to simulate.
public void unzip(String zipFile, String destDir)
{
try
{
int BUFFER = 8*1024;
File file = new File(zipFile);
ZipFile zip = new ZipFile(file);
String newPath = destDir;
new File(newPath).mkdir();
Enumeration zipFileEntries = zip.entries();
while (zipFileEntries.hasMoreElements())
{
ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
String currentEntry = entry.getName();
File destFile = new File(newPath, currentEntry);
File destinationParent = destFile.getParentFile();
destinationParent.mkdirs();
if (!entry.isDirectory())
{
BufferedInputStream is = new BufferedInputStream(zip
.getInputStream(entry));
int currentByte;
byte[] data = new byte[BUFFER];
FileOutputStream fos = new FileOutputStream(destFile);
BufferedOutputStream dest = new BufferedOutputStream(fos,
BUFFER);
while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
dest.write(data, 0, currentByte);
}
dest.flush();
dest.close();
is.close();
}
}
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
}

what does getNextEntry() do?

I have checked java api document, it says getNextEntry() Reads the next ZIP file entry and positions the stream at the beginning of the entry data.
what does it mean "reads the NEXT zip file"? why the "NEXT" ?
I have this piece of code, what's the point of this line ze = zin.getNextEntry()?
public void unzip() {
try {
FileInputStream fin = new FileInputStream(_zipFile);
ZipInputStream zin = new ZipInputStream(fin);
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
Log.v("Decompress", "Unzipping " + ze.getName());
if(ze.isDirectory()) {
_dirChecker(ze.getName());
} else {
FileOutputStream fout = new FileOutputStream(_location + ze.getName());
for (int c = zin.read(); c != -1; c = zin.read()) {
fout.write(c);
}
zin.closeEntry();
fout.close();
}
}
zin.close();
} catch(Exception e) {
Log.e("Decompress", "unzip", e);
}
}
It reads the next entry within the zip file.
A zip file logically contains main other files - so foo.zip can contain files a.txt and b.txt. The getNextEntry() moves you on to the next file within the archive.
(I've never been particularly keen on the way that ZipInputStream is modeled using inheritance from InputStream, but that's a different matter.)

Java - Zipping existing files [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Appending files to a zip file with Java
Hello Java Developers,
Here's the scenario:
Say I have a textfile named sample.txt. What I actually want to do is to put the sample.txt file into a *.zip file named TextFiles.zip.
Here's what I have learned so far.
try{
File f = new File(compProperty.getZIP_OUTPUT_PATH());
zipOut = new ZipOutputStream(new FileOutputStream(f));
ZipEntry zipEntry = new ZipEntry("sample.txt");
zipOut.putNextEntry(zipEntry);
zipOut.closeEntry();
zipOut.close();
System.out.println("Done");
} catch ( Exception e ){
// My catch block
}
My code so far creates a *.zip file and insert the sample.txt file.
My question is how would I be able to insert an existing file to the created *.zip file?
If your answer has anything to do with TrueZIP, please post an SSCCE.
I have done the following:
Googled
Search for existing question. ( Found few. No answer. Some didn't answer my particular question.
Read TrueZip. Yet, I couldn't understand a thing. ( Please do understand )
Using the inbuilt Java API. This will add a file to a Zip File, this will replace any existing Zip files that may exist, creating a new Zip file.
public class TestZip02 {
public static void main(String[] args) {
try {
zip(new File("TextFiles.zip"), new File("sample.txt"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static void zip(File zip, File file) throws IOException {
ZipOutputStream zos = null;
try {
String name = file.getName();
zos = new ZipOutputStream(new FileOutputStream(zip));
ZipEntry entry = new ZipEntry(name);
zos.putNextEntry(entry);
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
byte[] byteBuffer = new byte[1024];
int bytesRead = -1;
while ((bytesRead = fis.read(byteBuffer)) != -1) {
zos.write(byteBuffer, 0, bytesRead);
}
zos.flush();
} finally {
try {
fis.close();
} catch (Exception e) {
}
}
zos.closeEntry();
zos.flush();
} finally {
try {
zos.close();
} catch (Exception e) {
}
}
}
}
Here you can get answer for your question: http://truezip.schlichtherle.de/2011/07/26/appending-to-zip-files/
It seems that, according to the epic JDK reference, you could use a while zis.getNextEntry() != null loop to loop through the file (where zis is a ZipInputStream), then use zis.read() to read into an array, which is sent to an ArrayList or similar.
Then, one could use toArray(), "cast" it to a byte array with this method and zos.write() it into the output ZIP file (where zos is a ZipOutputStream), using zos.putNextEntry() to make new entries. (You will need to save the ZipEntry and get its name with ze.getName(), with ze being a ZipEntry.)You should replace T with Byte and byte (use byte everywhere but the for loop body) and may need to modify the casting code to use Byte.byteValue() to convert from Byte (wrapper class) to byte (primitive type), like so:
for(int i = 0; i < objects.length; i++) {
convertedObjects[i] = (Byte)objects[i].byteValue();
}
Note that this is untested and based on the JDK (entries ZipInputStream, ZipOutputStream, ArrayList, and Byte) and a Google search on array casting.
Sorry if that was a bit dense, and hope this helps!!

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).

Zipping and Unzipping Jar, It's not the same size!

I'm making a modding application for a game. When I unzip and zip the same files: for some reason although it is open-able with 7Zip, it's not open-able in the actual application. Even though I've not edited the unzipped files - it's missing a few bytes.
I gathered the methods from the net and have been editing and retrying for the last 5 hours without success, any help guys? Thanks!
Here's my code:
class zipper
{
static byte[] buffer = new byte[4096];
public static void unzip(File zipfile, File outputfolder) throws Exception
{
JarFile zip = new JarFile(zipfile);
Enumeration entries = zip.entries();
while(entries.hasMoreElements())
{
JarEntry entry = (JarEntry) entries.nextElement();
File unzipped = new File(outputfolder,entry.getName());
if (entry.isDirectory() && !unzipped.exists())
{
unzipped.mkdirs();
continue;
}
else if (!unzipped.getParentFile().exists())
unzipped.getParentFile().mkdirs();
InputStream in = zip.getInputStream(entry);
FileOutputStream fos = new FileOutputStream(unzipped);
int count;
while((count = in.read(buffer, 0, buffer.length)) != -1)
fos.write(buffer, 0, count);
// clean up
fos.close();
in.close();
}
}
public static void zip(File[] infiles, JarOutputStream jos) throws Exception
{
zip(infiles,"",jos);
// clean up
jos.flush();
jos.close();
}
public static void zip(File[] infiles, String basefolder, JarOutputStream jos) throws Exception
{
FileInputStream fis = null;
for(int i=0; i<infiles.length; i++)
{
if(infiles[i].isDirectory())
{
// recursive call for directories
zip(infiles[i].listFiles(), infiles[i].getName() + File.separator, jos);
continue;
}
String filepath = basefolder + infiles[i].getName();
JarEntry entry = new JarEntry(filepath);
jos.putNextEntry(entry);
fis = new FileInputStream(infiles[i]); // get stream
int count;
while((count = fis.read(buffer, 0, buffer.length)) != -1)
jos.write(buffer, 0, count);
}
}
}
Without debugging your code I can say that the most probable reason is the compression level. The default compression level is Deflater.DEFAULT_COMPRESSION. You can change it using ZipOutputStream.setLevel().
I believe that you created your original jar file using jar utility or some other zip creator. Then you created the same using your code and got different size. In this case the compression level may explain the difference.

Categories

Resources