UpdateFileStream - IOException

Jan 20, 2009 at 12:12 PM
Edited Jan 20, 2009 at 12:17 PM
Hi @all!
I'm using this nice ZipDll in my software and I have a problem with "UpdateFileStream" depending on how fast the target computer is.
What I want to do: Unzip a file from the Zip Archive by loading it into MemoryStream -> change this XML-File -> Update the Zip-File (the file inside the Zip-Archive) with the new MemoryStream.

Here's my code:

myZip =

new ZipFile(sFileName);
myZip.Password = Program.sZipPW;
MemoryStream machineDataStream = new MemoryStream();
string sInnerFileToLoadAsDataTable = "tblMachineData.xml";
string sFolderName = PLC_Fill_Methods.getFolderNameInZip(sFileName); // This method only checks if there is a folder inside the archive and if, what is its name - unimportant
myZip.Extract(sFolderName + sInnerFileToLoadAsDataTable, machineDataStream);

// These two lines are new but didn't solve the problem
myZip.Dispose();
myZip =
null;

 

 

XmlDocument x_doc = new XmlDocument();
machineDataStream.Seek(0,
SeekOrigin.Begin);
x_doc.Load(machineDataStream);
machineDataStream.Dispose();
machineDataStream =
null;

 

//update the XML File
XmlNode
x_nodeToChange = x_doc.SelectSingleNode("NewDataSet/tblMachineData[ParameterId = '" + sParamId + "']");
if (x_nodeToChange != null)
{
XmlNode x_ParamNode = x_nodeToChange.SelectSingleNode("Value");
x_ParamNode.InnerText = sValue;
}

 

MemoryStream newMachineDataStream = new MemoryStream();
x_doc.Save(newMachineDataStream);
newMachineDataStream.Seek(0,
SeekOrigin.Begin);

myZip =

new ZipFile(sKpdFilePath); // these two lines are also new but didn't solve the problem
myZip.Password =
Program.sZipPW;

 

 

myZip.UpdateFileStream(

"tblMachineData.xml", sFolderName, newMachineDataStream);

 

 

 

myZip.Save(); // here I will get the exception; not in Visual Studio or on a Pentium 4 but on fatser PCs like Core2Duo I get "The process cannot access the file "..." because it is being used by another process

newMachineDataStream.Dispose();
newMachineDataStream =

null;
myZip.Dispose();
myZip =
null;

What else can I do to manage my problem??? Any idea???

 

 

Jan 20, 2009 at 1:52 PM
Edited Jan 20, 2009 at 2:02 PM
Nobody with an idea??? Is there an yway to set the fileaccess free? Has such a issue never been tested, I can't believe! Please help!
Maybe I open the file for reading in a false way. But if so, are there other ways to open it???
Coordinator
Jan 21, 2009 at 3:41 PM
Jochen, gimme some time to have a look. . .
Coordinator
Jan 21, 2009 at 4:58 PM
I tried your general code - it worked for me, but I don't have a fast PC.

It's possible that there is a stream that is remaining open inadvertently after the call to x_doc.Save() . 
Could you please try to insert a the following lines into your code following the x_doc.Save() and before the myZip.Save()  ??

x_doc = null;
GC.Collect();

Here is my example:

        private void ModifyFileWithinZip()
        {
            using (var zip = ZipFile.Read(zipFileName))
            {
                XmlDocument doc = new XmlDocument();
                using (MemoryStream machineDataStream = new MemoryStream())
                {
                    zip.Extract(xmlFileName, machineDataStream);

                    machineDataStream.Seek(0, SeekOrigin.Begin);
                    doc.Load(machineDataStream);
                }

 
                //update the XML File
                XmlNode node = doc.SelectSingleNode(xpath);

                if (node != null)
                {
                    Console.WriteLine("Node xpath: {0}", xpath);
                    Console.WriteLine("current value: {0}", node.InnerText);
                    Console.WriteLine("new value: {0}", newvalue);
                    node.InnerText = newvalue;

                    using (MemoryStream newMachineDataStream = new MemoryStream())
                    {
                        doc.Save(newMachineDataStream);

                        // try this to close out any inadvertently open streams:
                        doc= null;
                        GC.Collect();

                        newMachineDataStream.Seek(0, SeekOrigin.Begin); 

                        zip.UpdateFileStream(xmlFileName, "", newMachineDataStream); 

                        // Here I will get the exception; not in Visual Studio or on a
                        // Pentium 4 but on faster PCs like Core2Duo I get "The process
                        // cannot access the file "..." because it is being used by
                        // another process.

                        zip.Save();
                    }

                }
            }
        }

Feb 22, 2011 at 3:26 PM
Edited Feb 22, 2011 at 3:27 PM

Hey guys, especially Cheeso; long time lurker here, finally had to post:

I would like to confirm the same behavior. You fix DOES help, but I am a little iffy about the reason and the fix approach. Specifically, there are cases where this explicit GC.Collect() call may not help.

What I do not understand is why we need to kill off XMLDocument. I checked the docs and yes, XMLDocument does not have IDispose interfaces (no using) and no explicit .Close() either. The reason as far as I can see it that the XMLDocument is just a memory struct, so why after .Save() is called on MemoryStream do we fail in .Save(ing) the zip file? Would it help to copy the stream into a new stream and then write *that* stream into the archive?

Oh and PS. UpdateEntry does not take full path like AddEntry does :( Or, it is somewhat confusing. AddEntry("\\path\\filename.txt") fails if entry is present but UpdateEntry("\\path\\filename.txt") just places the file in root :)

 

P.P.S. Thank you for your dedication and amazing work. Setup a donation page or something, I would most definitely drop some for you!

Coordinator
Feb 24, 2011 at 1:05 AM

Kommi - not sure about this old story.

I don't usually recommend GC.Collect(), ever, but this was a diagnostic and troubleshooting thing.

If you're having a problem I suggest you open a new thread to cover it.  This one is more than 2 years old, and surely is dealing with an older version of the library.

Also - regarding donations - there is a donation page.  Not sure how you missed it!

http://cheeso.members.winisp.net/DotNetZipDonate.aspx