I have to unzip a zip data package which is addressed via an URL. (The URL and DataInputStream are correct!)
private void unZipIt(File baseDir, DataInputStream dis, PipedOutputStream pos) throws ZipException
{
byte[] buffer = new byte[1024];
String fileName = "";
File newFile;
FileOutputStream fos = null;
try
{
ZipInputStream zis = new ZipInputStream(dis);
ZipEntry ze = zis.getNextEntry();
if(ze==null)
{
System.out.println("first zip entry is null");
}
while (ze != null)
{
System.out.println("zip entry is not null");
fileName = ze.getName();
newFile = new File(baseDir + File.separator + fileName);
if (isSavFile(fileName))
{
System.out.println(fileName + "is savfile");
new File(newFile.getParent()).mkdirs();
fos = new FileOutputStream(newFile);
int len;
while ((len = zis.read(buffer)) > 0)
{
fos.write(buffer, 0, len);
}
// fos.close();
}
ze = zis.getNextEntry();
}
zis.closeEntry();
zis.close();
// return true;
}
catch (IOException e)
{
// ex.printStackTrace();
log.error("unzipping '" + fileName + "'", e);
throw new ZipException(fileName, e);
// return false;
}
But it is not possible to get any of the zip entries. (first zip entry is null!)
With a FileOutputStream it worked perfectly. Because of the efficiency I am not allowed to store the file on the PC.
Anyone an idea?
Most likely the problem is with how you acquire the input stream you pass as dis to your unZipIt() method.
You should not receive a DataInputStream but rather a simple InputStream. ZipInputStream does not use nor expect input to be a DataInputStream.
Also when saving the content of an entry you should only read (and save) as many bytes as the length of the entry, not until there are more bytes.
Related
I have zip file on remote server, which I am accessing using JCIFS. I want to extract contents of that zip on remote server only. tried :
private void unzipFile(SmbFile zipFile) {
try {
String destPath = "//SHARED-PC/reports/";
int BUFFER_SIZE = 4096;
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destPath));
byte[] bytesIn = new byte[BUFFER_SIZE];
int read = 0;
while ((read = zipFile.getInputStream().read(bytesIn)) != -1) {
bos.write(bytesIn, 0, read);
}
bos.close();
}catch(Exception e) {
logger.error(" Error while unzipping zip file "+zipFile+" "+zipFile.getName());
e.printStackTrace();
}
}
But its alwayts reslting in errors
1. Access is Denied
2. I changed given path of dest folder - (The filename, directory name, or volume label syntax is incorrect)
Can someone suggest how it can be done? Thanx in advance
Update:
As per Petesh suggestion I used ZipInputStream to extract files from zip file.
i tried :
private static void unzip(SmbFile zipFilePath, String destDir) throws SmbException {
System.out.println(" Unzipping :: "+zipFilePath); //smb://WIN-B3TN6C0DC94/My_daily_reports/19-5-2018/Success/100-Sales-Records-19-5-2018.zip
System.out.println(" destdir is :: "+destDir); // smb://WIN-B3TN6C0DC94/My_daily_reports/19-5-2018/Success/
try {
ZipInputStream zis = new ZipInputStream(zipFilePath.getInputStream());
ZipEntry ze = zis.getNextEntry();
String fileName = ze.getName();
File newFile = new File(destDir);
System.out.println("newfile Path : "+newFile.getPath());
byte[] buf = new byte[1024];
String outputFilepathAndName = newFile.getPath() + File.separator + fileName;
System.out.println("outputFilepathAndName :: "+outputFilepathAndName);
OutputStream outputStream = new FileOutputStream(fileName);
while(ze != null){
int length;
while((length = zis.read(buf)) != -1) {
outputStream.write(buf, 0, length);
}
}
System.out.println("Write done // flushing now... ");
zis.closeEntry();
zis.close();
outputStream.close();
System.out.println(" UNZIP SUCCESSFUL "+fileName);
} catch (Exception e) {
System.out.println(" UNZIP ERROR");
e.printStackTrace();
}
}
But it gets stuck in while loop. Can anyone suggest what is going wrong here. I tried using OutputStream and BufferedOutputStream as well.
I have a zip file that contains a zip that includes folders to which I have to add some files. The structure is like
outerZip.zip
|folder
|innerZip.zip
|innerFolder
I need to add a few files to the inner folder.
I can return the innerZip ok, if I save it to file it shows the correct structure.
Now when I want to iterate through the ZipEntries of the innerZip for the first entry it shows to be /innerFolder, but when I want to add the entry content to the updated zip file it turns out that it contains data and throws the below error:
java.util.zip.ZipException: invalid entry CRC (expected 0x0 but got 0x46480bab)
at java.util.zip.ZipInputStream.read(ZipInputStream.java:218)
at java.io.FilterInputStream.read(FilterInputStream.java:107)
at zip.builder.InnerBuilder.addFilesToInnerZip(InnerBuilder.java:179)
at zip.builder.InnerBuilder.addFilesToZip(InnerBuilder.java:117)
The code is here:
private byte[] addFilesToZip(byte[] outerZipBytes, Set<File> files) {
String zipPath = System.getProperty("catalina.home") + File.separator + "outerZipFile.zip";
File zipFile = new File(zipPath);
ZipFile outerZipFile = null;
try {
zipFile.createNewFile();
FileOutputStream fileout = new FileOutputStream(zipFile);
fileout.write(outerZipBytes);
fileout.close();
outerZipFile = new ZipFile(zipFile);
File innerZipFile = getInnerZipFile(outerZipFile);
addFilesToInnerZip(innerZipFile, files);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (outerZipFile != null)
outerZipFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// TODO convert updated outer zip file to byte array
return new byte[0];
}
private File getInnerZipFile(ZipFile outerZipFile) throws IOException {
String innerZipPath = System.getProperty("catalina.home") + File.separator + "innerZipFile.zip";
ZipEntry entry = outerZipFile.getEntry("folder/inner.zip");
InputStream innerZipInputStream = outerZipFile.getInputStream(entry);
FileOutputStream fout = new FileOutputStream(new File(innerZipPath));
byte[] buf = new byte[1024];
int data;
while ((data = innerZipInputStream.read(buf)) != -1) {
fout.write(buf, 0, data);
}
innerZipInputStream.close();
fout.close();
return new File(innerZipPath);
}
private void addFilesToInnerZip(File zipFile, Set<File> files) throws IOException {
File tempFile = File.createTempFile(zipFile.getName(), null);
tempFile.delete();
zipFile.renameTo(tempFile);
byte[] buf = new byte[1024];
ZipInputStream zin = new ZipInputStream(new FileInputStream(tempFile));
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile));
ZipEntry entry = zin.getNextEntry();
while (entry != null) {
// Add ZIP entry to output stream.
out.putNextEntry(new ZipEntry(entry.getName()));
// Transfer bytes from the ZIP file to the output file
int len;
while ((len = zin.read(buf)) > 0) { // line 179
out.write(buf, 0, len);
}
entry = zin.getNextEntry();
}
for (File file : files) {
InputStream in = new FileInputStream(file);
out.putNextEntry(new ZipEntry("innerFolder/"+ file.getName()));
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
out.closeEntry();
in.close();
}
zin.close();
out.close();
tempFile.delete();
}
Thanks for any help!
I would like to unzip recursively some archive .zip.
I use java.util.zip and I can't use an other library.
My code :
public static void unzip(String file) {
try {
File fSourceZip = new File(file);
String zipPath = file.substring(0, file.length() - 4);
File temp = new File(zipPath);
temp.mkdir();
System.out.println(zipPath + " created");
ZipFile zipFile = new ZipFile(fSourceZip);
Enumeration e = zipFile.entries();
while (e.hasMoreElements()) {
ZipEntry entry = (ZipEntry) e.nextElement();
File destinationFilePath = new File(zipPath, entry.getName());
destinationFilePath.getParentFile().mkdirs();
if (entry.isDirectory()) {
continue;
} else {
System.out.println("Extracting " + destinationFilePath);
BufferedInputStream bis = new BufferedInputStream(
zipFile.getInputStream(entry));
int b;
byte buffer[] = new byte[1024];
FileOutputStream fos = new FileOutputStream(
destinationFilePath);
BufferedOutputStream bos = new BufferedOutputStream(fos,
1024);
while ((b = bis.read(buffer, 0, 1024)) != -1) {
bos.write(buffer, 0, b);
}
bos.flush();
bos.close();
bis.close();
}
if (entry.getName().endsWith(".zip")) {
// found a zip file, try to open
unzip(destinationFilePath.getAbsolutePath());
}
}
} catch (IOException ioe) {
System.out.println("IOError :" + ioe);
}
}
But I have some error with some archive :
Exception in thread "main" java.lang.IllegalArgumentException: MALFORMED
at java.util.zip.ZipCoder.toString(ZipCoder.java:58)
at java.util.zip.ZipFile.getZipEntry(ZipFile.java:567)
at java.util.zip.ZipFile.access$900(ZipFile.java:61)
at java.util.zip.ZipFile$ZipEntryIterator.next(ZipFile.java:525)
at java.util.zip.ZipFile$ZipEntryIterator.nextElement(ZipFile.java:500)
at java.util.zip.ZipFile$ZipEntryIterator.nextElement(ZipFile.java:481)
at zip.ReadingArchive.unzip(ReadingArchive.java:36)
at zip.ReadingArchive.unzip(ReadingArchive.java:82)
at zip.ReadingArchive.unzip(ReadingArchive.java:82)
at main.Main.main(Main.java:13)
I have this problem because there is .odp in my archive. How I can say only uses .zip, not other files ?
How I can resolve this problem ?
Thanks !
I've just fixed it by specifying alternative (non UTF-8) charset:
Charset CP866 = Charset.forName("CP866");
ZipFile zipFile = new ZipFile(zipArchive, CP866);
In your case, you need to specify another charset. Try, CP437, for instance.
I have this Java method to upload a file. I am trying to cater for users trying to upload a folder by compressing that folder into a zip file and upload it instead. For some reason in my case file.isDirectory() and file.isFile() are not working correctly.. even though the filename does not contain any extension, file.isFile() is returning true and isDirectory() returns false. Also directory.list() is also acting weird by returning null.
What can be the problem? Am I doing something wrong?
public File uploadFile(FileItem item, String filename, int ticket_id) throws IOException
{
FileOutputStream out = null;
InputStream fileContent = null;
File file = null;
try
{
//fullpath returns C://MyDocuments//zerafbe//Documents//apache-tomcat-7.0.29//webapps//attachments//t50\test
StringBuffer fullPath = new StringBuffer();
fullPath.append(Attachment.attachments_path);
fullPath.append("t");
fullPath.append(Integer.toString(ticket_id));
fullPath.append(File.separator);
fullPath.append(filename);
System.out.println("filename " + filename);
file = new File(fullPath.toString());
if (!file.exists())
{
// if directory does not exist, create it
file.getParentFile().mkdirs();
}
if (file.isFile())
{
// if file is not a folder
out = new FileOutputStream(file);
fileContent = item.getInputStream();
int read = 0;
final byte[] bytes = new byte[1024];
// read all the file and write it to created file
while ((read = fileContent.read(bytes)) != -1)
{
out.write(bytes, 0, read);
}
}
else if (file.isDirectory())
{
ZipFile appZip = new ZipFile(fullPath.toString());
appZip.generateFileList(file);
appZip.zipIt(filename + ".zip");
}
}
catch (FileNotFoundException e)
{
LogFile.logError("[FileUpload.uploadFile()] " + e.getMessage());
}
catch (IOException e1)
{
LogFile.logError("[FileUpload.uploadFile()] " + e1.getMessage());
}
finally
{
if (out != null)
{
out.close();
}
if (fileContent != null)
{
fileContent.close();
}
}
return file;
}
This is the ZipFile class I am using
public class ZipFile
{
List<String> fileList = null;
String source_folder = "";
public ZipFile(String source_folder)
{
fileList = new ArrayList<String>();
this.source_folder = source_folder;
}
public void zipIt(String zipFile)
{
byte[] buffer = new byte[1024];
String source = "";
try
{
try
{
source = source_folder.substring(source_folder.lastIndexOf("\\") + 1, source_folder.length());
}
catch(Exception e)
{
source = source_folder;
}
FileOutputStream fos = new FileOutputStream(zipFile);
ZipOutputStream zos = new ZipOutputStream(fos);
for (String file : this.fileList)
{
ZipEntry ze = new ZipEntry(source + File.separator + file);
zos.putNextEntry(ze);
FileInputStream in = new FileInputStream(source_folder + File.separator + file);
int len;
while ((len = in.read(buffer)) > 0)
{
zos.write(buffer, 0, len);
}
in.close();
}
zos.closeEntry();
//remember close it
zos.close();
}
catch(IOException ex)
{
ex.printStackTrace();
}
}
public void generateFileList(File node)
{
// add file only
if(node.isFile())
{
fileList.add(generateZipEntry(node.toString()));
}
if(node.isDirectory())
{
String[] subNode = node.list();
if (subNode != null) {
for(String filename : subNode)
{
generateFileList(new File (node, filename));
}
}
}
}
private String generateZipEntry(String path)
{
return path.substring(source_folder.length() + 1, path.length());
}
}
file.list() is being done in the generateFileList method in ZipFile class. I know this is returning null since I tried detecting whether the file is a folder or a file by using filename.indexOf(".") instead of isDirectory() and isFile() since they were not working. But I wish I had an explanation for this.
Thanks for your help!
if (!file.exists()) {
// if directory does not exist, create it
file.mkdirs();
}
will create directory and test file.isDirectory() will return true
It could be a problem with the path?
C://MyDocuments//zerafbe//Documents//apache-tomcat-7.0.29//webapps//attachments//t50\test
You are mixing backslash with slash...
I tested your code block
ZipFile appZip = new ZipFile(file.toString());
appZip.generateFileList(file);
appZip.zipIt(filename + ".zip");
with a local folder and it's working perfectly. I think you are passing a invalid path. This may be the cause isFile or isDirectory methods are acting strangely. Try to add a validation statement at the starting of generateFileList method using File API:
if(!node.exists) {
// return some flag to signify error OR throw a suitable Exception
}
This should work.
public String compressData(String srcDir) {
String zipFile = srcDir+".zip";
try {
// create byte buffer
byte[] buffer = new byte[1024];
FileOutputStream fos = new FileOutputStream(zipFile);
ZipOutputStream zos = new ZipOutputStream(fos);
File dir = new File(srcDir);
File[] files = dir.listFiles();
for (int i = 0; i < files.length; i++) {
System.out.println("Adding file: " + files[i].getName());
FileInputStream fis = new FileInputStream(files[i]);
// begin writing a new ZIP entry, positions the stream to the start of the entry data
zos.putNextEntry(new ZipEntry(files[i].getName()));
int length;
while ((length = fis.read(buffer)) > 0) {
zos.write(buffer, 0, length);
}
zos.closeEntry();
// close the InputStream
fis.close();
}
// close the ZipOutputStream
zos.close();
}
catch (IOException ioe) {
System.out.println("Error creating zip file" + ioe);
}
return zipFile;
}
I'm trying to extract .zip files and I'm using this code:
String zipFile = Path + FileName;
FileInputStream fin = new FileInputStream(zipFile);
ZipInputStream zin = new ZipInputStream(fin);
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
UnzipCounter++;
if (ze.isDirectory()) {
dirChecker(ze.getName());
} else {
FileOutputStream fout = new FileOutputStream(Path
+ ze.getName());
while ((Unziplength = zin.read(Unzipbuffer)) > 0) {
fout.write(Unzipbuffer, 0, Unziplength);
}
zin.closeEntry();
fout.close();
}
}
zin.close();
but the problem is that, while debugging, when the code reaches the while(!=null) part, the zin.getNextEntry() is always null so it doesnt extract anything..
The .zip file is 150kb.. How can I fix this?
The .zip exists
Code I use to dl the .zip:
URL=intent.getStringExtra("DownloadService_URL");
FileName=intent.getStringExtra("DownloadService_FILENAME");
Path=intent.getStringExtra("DownloadService_PATH");
File PathChecker = new File(Path);
try{
if(!PathChecker.isDirectory())
PathChecker.mkdirs();
URL url = new URL(URL);
URLConnection conexion = url.openConnection();
conexion.connect();
int lenghtOfFile = conexion.getContentLength();
lenghtOfFile/=100;
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(Path+FileName);
byte data[] = new byte[1024];
long total = 0;
int count = 0;
while ((count = input.read(data)) != -1) {
output.write(data, 0, count);
total += count;
notification.setLatestEventInfo(context, contentTitle, "جاري تحميل ملف " + FileName + " " + (total/lenghtOfFile), contentIntent);
mNotificationManager.notify(1, notification);
}
output.flush();
output.close();
input.close();
You might have run into the following problem, which occurs, when reading zip files using a ZipInputStream: Zip files contain entries and additional structure information in a sequence. Furthermore, they contain a registry of all entries at the very end (!) of the file. Only this registry does provide full information about the correct zip file structure. Therefore, reading a zip file in a sequence, by using a stream, sometimes results in a "guess", which can fail. This is a common problem of all zip implementations, not only for java.util.zip. Better approach is to use ZipFile, which determines the structure from the registry at the end of the file. You might want to read http://commons.apache.org/compress/zip.html, which tells a little more details.
If the Zip is placed in the same directory as this exact source, named "91.zip", it works just fine.
import java.io.*;
import java.util.zip.*;
class Unzip {
public static void main(String[] args) throws Exception {
String Path = ".";
String FileName = "91.zip";
File zipFile = new File(Path, FileName);
FileInputStream fin = new FileInputStream(zipFile);
ZipInputStream zin = new ZipInputStream(fin);
ZipEntry ze = null;
int UnzipCounter = 0;
while ((ze = zin.getNextEntry()) != null) {
UnzipCounter++;
//if (ze.isDirectory()) {
// dirChecker(ze.getName());
//} else {
byte[] Unzipbuffer = new byte[(int) pow(2, 16)];
FileOutputStream fout = new FileOutputStream(
new File(Path, ze.getName()));
int Unziplength = 0;
while ((Unziplength = zin.read(Unzipbuffer)) > 0) {
fout.write(Unzipbuffer, 0, Unziplength);
}
zin.closeEntry();
fout.close();
//}
}
zin.close();
}
}
BTW
what is the language in that MP3, Arabic?
I had to alter the source to get it to compile.
I used the File constructor that takes two String arguments, to insert the correct separator automatically.
Try this code:-
private boolean extractZip(String pathOfZip,String pathToExtract)
{
int BUFFER_SIZE = 1024;
int size;
byte[] buffer = new byte[BUFFER_SIZE];
try {
File f = new File(pathToExtract);
if(!f.isDirectory()) {
f.mkdirs();
}
ZipInputStream zin = new ZipInputStream(new BufferedInputStream(new FileInputStream(pathOfZip), BUFFER_SIZE));
try {
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
String path = pathToExtract +"/"+ ze.getName();
if (ze.isDirectory()) {
File unzipFile = new File(path);
if(!unzipFile.isDirectory()) {
unzipFile.mkdirs();
}
}
else {
FileOutputStream out = new FileOutputStream(path, false);
BufferedOutputStream fout = new BufferedOutputStream(out, BUFFER_SIZE);
try {
while ( (size = zin.read(buffer, 0, BUFFER_SIZE)) != -1 ) {
fout.write(buffer, 0, size);
}
zin.closeEntry();
}catch (Exception e) {
Log.e("Exception", "Unzip exception 1:" + e.toString());
}
finally {
fout.flush();
fout.close();
}
}
}
}catch (Exception e) {
Log.e("Exception", "Unzip exception2 :" + e.toString());
}
finally {
zin.close();
}
return true;
}
catch (Exception e) {
Log.e("Exception", "Unzip exception :" + e.toString());
}
return false;
}
This code works fine for me. Perhaps you need to check that the zipFile String is valid?
String zipFile = "C:/my.zip";
FileInputStream fin = new FileInputStream(zipFile);
ZipInputStream zin = new ZipInputStream(fin);
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
System.out.println("got entry " + ze);
}
zin.close();
produced valid results on a 3.3Mb zip file.
This code seems to work correctly for me.
Are you sure that your zip file is a valid zip file? If the file does not exist or is not readable then you will get a FileNotFoundException, but if the file is empty or not a valid zip file, then you will get ze == null.
while ((ze = zin.getNextEntry()) != null) {
The zip that you specify isn't a valid zip file. The size of the entry is 4294967295
while ((ze = zin.getNextEntry()) != null) {
System.out.println("ze=" + ze.getName() + " " + ze.getSize());
UnzipCounter++;
This gives:
ze=595.mp3 4294967295
...
Exception in thread "main" java.util.zip.ZipException: invalid entry size (expected 4294967295 but got 341297 bytes)
at java.util.zip.ZipInputStream.readEnd(ZipInputStream.java:386)
at java.util.zip.ZipInputStream.read(ZipInputStream.java:156)
at java.io.FilterInputStream.read(FilterInputStream.java:90)
at uk.co.farwell.stackoverflow.ZipTest.main(ZipTest.java:29)
Try your code with a valid zip file.
I know it's late for answer but anyway ..
I think the problem is in
if(!PathChecker.isDirectory())
PathChecker.mkdirs();
it should be
if(!PathChecker.getParentFile().exists())
PathChecker.getParentFile().mkdirs();