simple copy zip file, unzip, delete zip file throws IOException

Mar 16, 2009 at 6:53 PM
Edited Mar 16, 2009 at 7:01 PM
Hello,

I am using DotNetZip version 1.7.2.12 for .NET 2.0.  When I try to run the operation below, it throws an IOException (especially after the 2nd run).  I have tried several things including explicitly closing the file and calling GC collection.  This IOException only happens if I run the unzip function.  If I comment out the "Using" statement block, it runs successfully.  Is the unzip function somehow hanging onto the file?  Is my code correct?

Thanks in advance,

Error:
{"The process cannot access the file 'D:\\test\\dest\\Temp_Backup\\source.zip' because it is being used by another process."}

Code:

 

static void TestNewUnzipping()

 

{

 

string src = @"D:\test\source\source.zip";

 

 

string dest = @"D:\test\dest\Temp_Backup\source.zip";

 

 

string outputFolder = @"D:\test\dest\Temp_Backup\";

 

 

File.Copy(src, dest, true);

 

 

using (Ionic.Zip.ZipFile zip = Ionic.Zip.ZipFile.Read(dest))

 

{

 

foreach (Ionic.Zip.ZipEntry e in zip)

 

{

 

 

//e.Extract(outputFolder, true);

 

e.ExtractWithPassword(outputFolder,

true, "1234");

 

}

 

//zip.Dispose();

 

 

//GC.Collect();

 

}

 

File.Delete(dest);

 

}

Coordinator
Mar 22, 2009 at 6:53 AM

In theory what you are doing should work, but there are some possibilities for confusion or errors.
Can you post the stacktrace that you get with the exception?  You have said it is an exception, but you haven't said WHERE you get the exception.

On the File.Delete() ? On the ZipFile.Read()?   on the File.Copy() ? 

When you extract files, you appear to be extracting to the same directory that contains the zipfile you are reading.
If there is contained within the zipfile, a file with the same name as the one you are reading, then you will likely get an exception.
In other words if "source.zip" contains an entry by the name of "source.zip", then the e.Extract() will try to overwrite a file that is in use.

You should not have to explicitly call zip.Dispose() nor GC.Collect().  In fact, as a rule, NEVER EVER EVER call GC.Collect().   You likely don't need it.   The runtime is almost always smarter than you are about when it needs to do garbage collection!

Why are you copying the file anyway?  Why not just read it from the original location?
Why copy the file, only to read and then delete it? 

Apr 15, 2009 at 12:15 PM
Edited Apr 15, 2009 at 3:51 PM
Same error here, the exception raises on File.Delete(). Im using the Compact Framework version on a PDA


ZipFile zip = ZipFile.Read(pathFileZIP);
            foreach (ZipEntry e in zip)
            {
                if (password.Length != 0)
                {
                    e.ExtractWithPassword(directorio, password);  // overwrite == true
                }
                else
                {
                    e.Extract(directorio);
                }
            }
            zip.Dispose();
            zip = null;
System.IO.File.delete(pathFileZIP); // IOException The process cannot access the file 'xxxx.zip' because it is being used by another process.

I've tried too with using() and the same exception raises
Coordinator
Apr 16, 2009 at 2:15 AM
Edited Apr 16, 2009 at 2:15 AM
Though the exception here is the same as the original message, I don't think it's the same situation.  The first message had a zip file that contained a zip file of the same name.  It seemed that the extraction was extracting over the original zip file. OR at least there was a chance of that.  In any case, the code didn't make a ton of sense to me.  I never got a reply. 

The key thing for you is the use of the library on the CF.  There is no Dispose() on a Stream in .NET CF.  So, when you call ZipFile.Dispose(), it does not translate into a Dispose() on the corresponding stream that is used to read the zip file.  This is just the way the compact framework was designed.  It seems that the file pointer is not yet closed when you try to delete the file. 

What I suggest is this: try a back-off interval.  Something like this:
bool retry = true;
while (retry)
{
  try 
  {
    System.IO.File.Delete(pathFileZIP);
    retry = false;
  }
  catch (Exception e1)
  {
    retry = WantAnotherRetry();
  }
if (retry) Thread.Sleep(delayInterval); }

The criteria for continuing to retry could be, the number of attempts, or a time interval (you'd have to get the time before you start trying to delete, and then subtract it from the time of the current attempt), or something else. Up to you.

Apr 16, 2009 at 9:33 AM
well, I think too is not the same situation but...the title of the discussion is better fitting my issue i think.

With the back-off interval  i finally can delete the file , but at the same time makes the library unusable, it takes at least 40 seconds to delete a 3k zip file.

So...
Connecting FTP ..less than 1 second
downloading file ..less than 1 second
extracting files .. less than 0.5 seconds
deleting file... 40-60 seconds....???

I'm actually using another library to manage the unzip and i can delete the file inmediatly (but it has other issues xd) . So i think it must be an issue of DotNetzip.

Thanks in advance.





Jul 6, 2010 at 5:00 PM

I had the same problem as diesalher

 

Now I use:

 

                        System::IO::FileStream^ fs = System::IO::File::OpenRead(fileName);

                        ZipFile^ zip = ZipFile::Read(fs);
                        
                        for each (ZipEntry^ e in zip)
                        {
                            e->Extract(Folder, ExtractExistingFileAction::OverwriteSilently);
                        }
                        fs->Close();