Home Forums .NET libraries Xceed Zip & Real-Time Zip for .NET Overwrite a file in a TarArchive, while reading another file

Viewing 4 posts - 1 through 4 (of 4 total)
  • Author
    Posts
  • User (Old forums)
    Member
    Post count: 23064
    #20023 |

    Hi,

    I need to overwrite a file in a existing TarArchive. This itself is not a problem and it works. Where I struggle is when I have opened a File for reading (with “GetFile(filename).OpenRead(FileShare.ReadWrite)”) at the same time. What happens now is that I get the Excpetion  “Xceed.FileSystem.ItemAlreadyExistsException” when I now try to overwrite the file with: CreateFile(filename, true).

    I tried also to use GetFile(filename).OpenWrite(true) instead of CreateFile. What happens now is, that Xceed writes the new file into the temporary folder, but never writes back into the TarArchive, also not when I close all streams and the TarArchive.

    After several tests I assumed it is not possible to write and read at the same time. Because of that I closed all open streams before overwriting the file in the TarArchive – and guess what it still didn’t work! Sometimes this solution works, if I call GC.Collect() before overwriting the file. Somehow, I assume, Xceed keeps a handle to the TarArchiveFile which is only removed in the finalize method. Unfortunately I can find a possibility to force that this handle is released.

    Can anybody help me?
    => Is there a possibilty to overwrite a file while reading another file from a tar archive?
    => Is there a possibility to force the TarArchive to release all handles to the file system?

    Regards,

    Roman

     

     

     

    Imported from legacy forums. Posted by huer12 (had 1304 views)

    User (Old forums)
    Member
    Post count: 23064

    It is difficult to tell without seeing how you release your resources.

    A possible solution is to use “using” clause with the streams, so that when you get out of the using, the file should  be free to do something else with it.

    e.g. :

    using( Stream stream = TarArchive.GetFile(filename).OpenRead(FileShare.ReadWrite) )

    {

       //loop on the stream to read the file

    }

    Another possible solution is to use AutoBatchUpdate around the TarArchive, which should alleviate the problem.

     

    Imported from legacy forums. Posted by André (had 357 views)

    User (Old forums)
    Member
    Post count: 23064

    I release the stream by calling stream.close() and additionally I set all references to null, respectivly I clear the list which holds the streams.

    In the meantime I found a solution. If I call  GC.Collect() and  GC.WaitForPendingFinalizers() before overwriting the file it works. Therefore a object must keep a reference to the file handle until the finalizer is called!

    So what I do is:

    First the file is opened and is kept open for reading

    private Stream _contentStream;
    public void OpenContent(string filename)
    {
         DiskFile tarFile = new DiskFile(filename);
       
    TarArchive ta = new TarArchive(_tarFile);
           _contentStream = _ta.GetFile(“Content”).OpenRead();
    …. // read the file
    }
    public void ReadPosition(int pos)
    {
            byte[] ba = new byte[25];
            _
    contentStream.Read(ba, 0, sizeof(UInt32));
    }

    Later the customer presses the Safe button on the GUI

    public void SafeLayout(string filename)
    {
           _contentStream.Close();
           _contentStream = null;

            GC.Collect();
            GC.WaitForPendingFinalizers();
            DiskFile tarFile = new DiskFile(filename);
          
    TarArchive ta = new TarArchive(_tarFile);
            stream = archive.CreateFile(“Layout”, true);
           …. // write into stream
           stream.Close()
    }

    This is simpliyfied code. In real I open several files in the archive for reading.

    If I don’t call the two GC methods, it does not work. Then the the Excpetion  “Xceed.FileSystem.ItemAlreadyExistsException” is thrown. With the two GC calls it works

    So one of your classes must keep a reference to the file handle until the finalizer is called. => In my opinion this is a bug!

    Imported from legacy forums. Posted by huer12 (had 422 views)

    User (Old forums)
    Member
    Post count: 23064

    If you open several streams from the TarArchive and you only close some of them, you will get the exception if you create another instance of TarArchive for one that was previously opened. You should try to keep the reference to the TarArchive for the lifetime of your Application. Also, when you use a stream for reading, try to use the using statement to correctly close the stream every time you access it from within the TarArchive. Here is your code snippet a bit modified according to our suggestions:

    private TarArchive m_tarArchive;

    private void OpenTarArchive( string fileName )
    {
      DiskFile tarFile = new DiskFile( fileName );

      m_tarArchive = new TarArchive( tarFile );
    }

    private void ReadPosition( int pos )
    {
      using( Stream stream = m_tarArchive.GetFile( “Content” ).OpenRead() )
      {
        // Read file and close the stream right after
      }
    }

    private Stream OpenAndReadTarredFile( string fileName )
    {
      AbstractFile tarredFile = m_tarArchive.GetFile( fileName );

      if( tarredFile.Exists == false )
        tarredFile.Create();

      return tarredFile.OpenRead();
    }

    private void DoSomethingWithOpenedTarredFile( string fileName )
    {
      using( Stream stream = OpenAndReadTarredFile( fileName ) )
      {
        // read content of the file as stream and release the reference to the stream
      }
    }

    private void SafeLayout()
    {
      AbstractFile layoutFile = m_tarArchive.GetFile( “Layout” );

      if( layoutFile.Exists == true )
        layoutFile.Delete();

      using( Stream stream = layoutFile.CreateWrite() )
      {
        // write to stream
      }
    }

    Imported from legacy forums. Posted by André (had 1674 views)

Viewing 4 posts - 1 through 4 (of 4 total)
  • You must be logged in to reply to this topic.