0 votes
by (320 points)
edited

I am getting "File in Access " error when I am trying to zip a set of files. I basically take some files and place them in multiple folders. I will be taking the same set of files and placing them in multiple folders. So, if the first file is taken , then the zipping utility should not "hold" it anymore, but it looks like it holds and that too it holds them in "ReadWrite" mode, because I get "File in Access" error. I am accessing all the files only in "Read" mode, why does still Rebex take them in "ReadWrite" mode ? I am not getting the error when I unzip it with some other utility and I have also checked nobody tries to access those files which continuously give "File in Access" errors. So I am suspecting that Rebex zips it up pretty fast and hence it cant release the "hold" it has. But, why should it have the "hold" on a file in first place when I am only opening it in "Read" mode. Please see the code below :

using (MemoryStream memoryStream = new MemoryStream(capacity))
{
    foreach (Medispan.Zip.ZipCommand zipCommand in zipCommands)//Zipcommands will have the path for files
    {
        if (zipCommand.IsDirectory)
            continue;

        using (ZipArchive archive = new ZipArchive(memoryStream, ArchiveStreamCloseMode.LeaveOpen))
        {
            string zipArchiveFilePath = zipCommand.Destination.ToString();

            try
            {
                archive.AddFile(zipCommand.Source.GetStream(FileMode.Open, FileAccess.Read), @zipArchiveFilePath);
            }
            catch (ZipException ex)
            {
                _traceSource.TraceEvent(TraceEventType.Verbose, 1, "ZipException" + ex.Message);

                if (ex != null && !ex.Message.StartsWith("File with the same name already exists"))
                    throw ex;
            }
            catch (Exception exMessage)
            {
                _traceSource.TraceEvent(TraceEventType.Verbose, 1, "Exception" + exMessage.Message);

                if (memoryStream != null)
                {
                    memoryStream.Dispose();
                    memoryStream.Close();
                }
                throw exMessage;
            }
        }
    }

    memoryStream.Seek(0, SeekOrigin.Begin);
}
Applies to: Rebex ZIP

3 Answers

0 votes
by (72.7k points)
edited

Please note, that the stream given to the AddFile method is not closed after the method is finished. It is responsibility of the caller to close the given stream if needed.

Also please note, that the "File in Access" error doesn't depend on the FileAccess.ReadWrite, but on the FileShare which is by default FileShare.None.

What you probably need is to use the AddFile(string, string) method. It opens the file with following settings (and also closes it when reading is finished):

File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read);

So I suggest you to update your code like this:

using (MemoryStream memoryStream = new MemoryStream(capacity))
{
    // zipCommandswill have the path for files
    foreach (Medispan.Zip.ZipCommand zipCommand in zipCommands)
    {
        if (zipCommand.IsDirectory)
            continue;

        using (ZipArchive archive = new ZipArchive(memoryStream, ArchiveStreamCloseMode.LeaveOpen))
        {
            string zipArchiveFilePath = zipCommand.Destination.ToString();

            try
            {
                archive.AddFile(zipCommand.Source.ToString(), zipArchiveFilePath);
            }
            catch (ZipException ex)
            {
                _traceSource.TraceEvent(TraceEventType.Verbose, 1, "ZipException " + ex);

                if (ex.ProblemType != ArchiveProblemType.FileExists)
                    throw;
            }
            catch (Exception ex)
            {
                _traceSource.TraceEvent(TraceEventType.Verbose, 1, "Exception " + ex);
                throw;
            }
        }
    }

    memoryStream.Seek(0, SeekOrigin.Begin);
}
0 votes
by (320 points)
edited

Ok. Let me try what you are telling, but I got a doubt. Why do I need to close the stream associated to the "AddFile" method. I hope you are talking about the variable "archive". "Archive" is declared in the using block, wouldn't "using" take care of closing this ? Ok, if it doesn't , then I can close it after the exception on a finally block. If so, can I close it as archive.Close(ArchiveSaveAction.Auto); or Should I use rchive.Close(ArchiveSaveAction.None) or probably rchive.Close(ArchiveSaveAction.Shrink) ?

0 votes
by (72.7k points)
edited

No. I don't mean closing ZipArchive (after all it is associated with MemoryStream, so there is no file lock causing "File in Access" error). I really mean closing the file stream supplied to the AddFile method.

Closing of ZipArchive in this case is not necessary, it is correctly done by using clause.

If you are still receiving the error, please post here the received exception. In this case do it like this:

catch (Exception ex)
{
    // please post here the content of the exString
    string exString = ex.ToString();
}
...