I am facing an unusal issue.I am building a tool which is scheduled to run every 5 mins.
It will pick up the zip files from a particular directory and extract files (depending on the file name) to a destination. I am using zipentry to get each filename in zip file and then extracting as required then I back them (zip files, once I finish all the files in a zip) to a particular directory and then delete the zip file. But sometimes (not always) the zip files do not get deleted. Since I am using fileutils.forcedelete(). I am getting an exception: unable to delete file. So I changed to the code to using fileutils.forcedeleteonexit() still some files remain in the source.
Here is a sample of my code:
sourceFile=new file(zipfile);
zipFile = new ZipFile(sourceFile);
zEnum = (Enumeration<ZipEntry>) zipFile.entries();
for (int a = 0; a < zipFile.size(); a++)
{
ZipEntry zE = zEnum.nextElement();
//Function uses zip4j for extracting. No streams used.
extract(String sourceZipFile, String fileNameToExtract, String outputFolder);
}
//I tried it with finally either
zipFile.close();
//Using fileutils to copy. No streams used.
copyFile(sourceFile, backup);
FileUtils.forceDeleteOnExit(sourceFile);
There are no streams used but I am getting a lock on files sometimes (not always).
What seems to be the bug here? Is it the zip4j extraction that is causing the problem or anything else? I am using zip4j 1.3.1.
I think your problem related with OS file buffers, that sometimes are not flushed when you are trying to delete file.
Did you try to use sourceFile.deleteOnExit() instead FileUtils.forceDeleteOnExit(sourceFile)?
Also you can try to check sourceFile.canWrite before deleting (may be it may helps)
You can also try to use FileInputStream() before deleting:
FileInputStream fi = new FileInputStream(sourceFile);
fi.getFD().sync();
Use apache-commons IO's FileDeleteStrategy. Something like:
FileDeleteStrategy.FORCE.delete(file);
Update:
It should be the way IO is being handled in your application. I have written simple code which copies a zip file to a temporary zip, deflates the temporary zip and after few seconds deletes it. Here you go:
public class ZipTest {
private static String dirPath = "/home/ubuntuuser/Desktop/";
public static void main(String[] args) throws Exception {
File myzip = new File(dirPath + "content.zip");
String tempFileStr = dirPath + "content_temp.zip";
File tempFile = new File(tempFileStr);
String unzipFolderStr = dirPath + "unzip";
copyUsingChannels(myzip, tempFile);
// copyUsingStreams(myzip, tempFile);
unZip(tempFileStr, unzipFolderStr);
Thread.sleep(3000);
tempFile.delete();
}
private static void copyUsingStreams(File myzip, File tempFile)
throws IOException, FileNotFoundException {
byte[] barray = new byte[1024];
if (!tempFile.exists())
{
tempFile.createNewFile();
}
FileOutputStream fos = new FileOutputStream(tempFile);
FileInputStream fis = new FileInputStream(myzip);
int length = 0;
while ((length = fis.read(barray)) != -1)
{
fos.write(barray, 0, length);
}
fis.close();
fos.close();
}
public static void copyUsingChannels(final File srcFile, final File destFile) throws Exception
{
if (!destFile.exists())
{
destFile.createNewFile();
}
FileChannel source = new FileInputStream(srcFile).getChannel();
FileChannel destination = new FileOutputStream(destFile).getChannel();
source.transferTo(0, source.size(), destination);
source.close();
destination.close();
}
private static void unZip(String zipFile, String outputFolder) throws Exception {
byte[] buffer = new byte[1024];
File folder = new File(outputFolder);
if (!folder.exists()) {
folder.mkdir();
}
ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile));
ZipEntry ze = zis.getNextEntry();
while (ze != null) {
String fileName = ze.getName();
File newFile = new File(outputFolder + File.separator + fileName);
System.out.println("file unzip : " + newFile.getAbsoluteFile());
new File(newFile.getParent()).mkdirs();
if (ze.isDirectory())
{
newFile.mkdir();
ze = zis.getNextEntry();
continue;
}
FileOutputStream 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();
}
}
Related
I want to unzip and read the xml file data without actually unzipping or extracting the zip file in my project folder. How can I do this.
I have written code to unzip a file and make directory but I don't know how to do it without actually extracting.
My code -
public class ZipFile {
public static void main(String[] args) throws IOException {
String zipFileName = "people.zip";
String destDirectory = "src/main/xmlfiles";
File destDirectoryFolder = new File(destDirectory);
if(!destDirectoryFolder.exists()){
destDirectoryFolder.mkdir();
}
byte[] buffer = new byte[1024];
ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFileName));
ZipEntry zipEntry = zis.getNextEntry();
while (zipEntry != null){
String filePath = destDirectory + File.separator + zipEntry.getName();
System.out.println("unzipping "+ filePath);
if(!zipEntry.isDirectory()){
FileOutputStream fos = new FileOutputStream(filePath);
int len ;
while((len = zis.read(buffer)) > 0){
fos.write(buffer, 0 ,len);
}
fos.close();
}
else{
File dir = new File(filePath);
dir.mkdir();
}
zis.closeEntry();
zipEntry = zis.getNextEntry();
}
zis.closeEntry();
zis.close();
System.out.println("Unzip complete");
}
}
I also want to read the xml file, without parser I just want to read it like normal xml file. Anyone can please give me any idea how to do it what should I need to learn! Thanks
I have a zip file in assets. On first run of app, zip file (all files and folders) gets unzipped and stored in internal storage area. The base unzipped path is getFilesDir(). Since zip also contains folders, i could not use openFileOutput as it gave an error, contains a path separator. So i have used FileOutputStream instead which is now working fine. Since FileOutputStream does not expect private flag. Are these unzipped files and folders are private to my app or can they be accessed from other apps?
Here's the code,
`public boolean unpackZip(InputStream is, String path) throws IOException {
String filename;
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(is));
ZipEntry ze;
byte[] buffer = new byte[1024];
int count;
while ((ze = zis.getNextEntry()) != null) {
filename = ze.getName();
// Need to create directories if not exists, or
// it will generate an Exception...
if (ze.isDirectory()) {
File fmd = new File(path + filename);
fmd.mkdirs();
continue;
}
FileOutputStream fout = new FileOutputStream(path + filename);
while ((count = zis.read(buffer)) != -1) {
fout.write(buffer, 0, count);
}
fout.close();
zis.closeEntry();
}
zis.close();
return true;
}`
i am trying to create a method which copies a java.io.File into a java.util.zip.ZipFile. For this i first open a java.util.zip.ZipOutputStream of the ZipFile, then create a new java.util.zip.ZipEntry with the name of the file, put that new ZipEntry in the ZipOutputStream and then write the content of the File to the ZipOutputStream. After that i flush the ZipOutputStream and close all streams.
For some reason i can't explain this procedure removes all other ZipEntries from the ZipFile and only leaves the copied one in there. Here is the code for copying the file (the file is represented by the java.io.InputStream parameter)
public static boolean compress(final InputStream pSourceStream, final ZipFile pTarget, final ZipEntry pContainer,
final String pFileName) {
if (pSourceStream != null && pTarget != null && pFileName != null && !pFileName.isEmpty()) {
try {
final ZipOutputStream output = new ZipOutputStream(new FileOutputStream(new File(pTarget.getName())));
final ZipEntry target = (pContainer != null) ? new ZipEntry(pContainer.getName() + pFileName)
: new ZipEntry(pFileName);
output.putNextEntry(target);
final byte[] buffer = new byte[BUFFER_SIZE];
int readBytes;
while ((readBytes = pSourceStream.read(buffer)) != -1) {
output.write(buffer, 0, readBytes);
}
pSourceStream.close();
output.flush();
output.close();
return true;
} catch (final IOException ignore) {
// took care of target
// ios will return false
}
}
return false;
}
Here is my code which calls this method
public static void main(final String[] args) throws ZipException, IOException {
final Package p = FileHandler.class.getPackage();
final InputStream classStream = FileHandler.stream(p, "FileHandler.class");
FileHandler.compress(classStream, new ZipFile(new File("C:/Users/litts/Desktop/FileHandlerTest/TestZip.jar")),
"FileHandler1.class");
}
So what im basicly doing here is copying the class-file of FileHandler to a zip-file. But all of its other content is removed when doing so.
You are not reading in the Zip file, you are just overwriting it at the file level.
Using the NIO.2 File API copying files to zip files becomes much easier.
Try (untested):
try (FileSystem zipFS = FileSystems.newFileSystem(URI.create("jar:" + zipURI), Collections.<String, Object>emptyMap())) {
Path targetInZipPath = zipFS.getPath(targetInZipPathString);
Files.copy(srcPath, targetInZipPath);
}
My UnZip class does not unzip whole the file. This class is called from another activity. My zip file is saved in the main directory of the phone's internal storage. The zip file has folders and some video.
What's wrong with this unzip?
What and how should I read file from zip' decompress and unzip is the same meaning?
Thanks for your help!
public class Unzip {
private static final String INPUT_ZIP_FILE = "sdcard/downloaded_issue.zip";
private static final String OUTPUT_FOLDER = "sdcard/Atlantis/";
public static void main()
{
Unzip unZip = new Unzip();
unZip.unZipIt(INPUT_ZIP_FILE, OUTPUT_FOLDER);
}
/**
* Unzip it
* #param zipFile input zip file
* #param outputFolder zip file output folder
*/
public void unZipIt(String zipFile, String outputFolder){
byte[] buffer = new byte[1024];
try{
//create output directory is not exists
File folder = new File(OUTPUT_FOLDER);
if(!folder.exists()){
folder.mkdir();
}
//get the zip file content
ZipInputStream zis =
new ZipInputStream(new FileInputStream(zipFile));
//get the zipped file list entry
ZipEntry ze = zis.getNextEntry();
while(ze!=null){
String fileName = ze.getName();
File newFile = new File(outputFolder + File.separator + fileName);
System.out.println("file unzip : "+ newFile.getAbsoluteFile());
//create all non exists folders
//else you will hit FileNotFoundException for compressed folder
new File(newFile.getParent()).mkdirs();
FileOutputStream fos = new FileOutputStream(newFile);
int len;
while ((len = zis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fos.close();
if (ze.isDirectory()) {
ze = zis.getNextEntry();
}
}
zis.closeEntry();
zis.close();
System.out.println("Done");
}catch(IOException ex){
ex.printStackTrace();
}
}
}
I think your 'while' loop is broken; you're only fetching the next entry if that next entry is a directory, while I assume you're probably trying to skip the directories.
Anyway, since you create the folders for all files you encounter, you can just skip the folder entries and write the file entries. The only exception would be the creation of empty folders.
Replacing the while-loop by this code should work:
while(ze!=null){
String fileName = ze.getName();
File newFile = new File(outputFolder + File.separator + fileName);
System.out.println("file unzip : "+ newFile.getAbsoluteFile());
//create all non exists folders
//else you will hit FileNotFoundException for compressed folder
if (ze.isDirectory()) {
// create the folder
newFile.mkdirs();
}
else {
// create the parent folder and write to disk
new File(newFile.getParent()).mkdirs();
FileOutputStream fos = new FileOutputStream(newFile);
int len;
while ((len = zis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fos.close();
}
// get the next item
ze = zis.getNextEntry();
}
if(!ErmUtil.isNull(listOfActualFilePaths) && listOfActualFilePaths.size()>0){
FileOutputStream fos = new FileOutputStream("/smiles/wrk/attachments/ermWeb/taxation/testing.zip");
ZipOutputStream zos = new ZipOutputStream(fos);
Iterator itrOnFNames = listOfActualFilePaths.iterator();
while (itrOnFNames.hasNext()) {
StringBuffer ActualPath = (StringBuffer) itrOnFNames.next();
addToZipFile(ActualPath.toString(), zos);
}
zos.close();//Closing Both Streams
fos.close();
}
public void addToZipFile(String fileName, ZipOutputStream zos) throws FileNotFoundException, IOException {
System.out.println("Writing '" + fileName + "' to zip file");
File file = new File(fileName);
int index = fileName.lastIndexOf("/");
String fileNameForZip = fileName.substring(index+1);
FileInputStream fis = new FileInputStream(file);
ZipEntry zipEntry = new ZipEntry(fileNameForZip);
zos.putNextEntry(zipEntry);
byte[] bytes = new byte[1024];
int length;
while ((length = fis.read(bytes)) >= 0) {
zos.write(bytes, 0, length);
}
zos.closeEntry();
fis.close();
}
I am using above code, to save zip-ed file on a specific location. But what i want to do is that, instead of saving that file, it get downloaded directly.
Edit 1
See If I want to download a zip file,then according to above code, on path /smiles/wrk/attachments/ermWeb/taxation/testing.zip it will be saved first,then from that folder, I(server) can send it to client(Computer).
But I don't want to save it on the specified path,Instead of "saving first to folder and then sending to client", I directly want to send it to client.