Ben Clarke
Ben Clarke

Reputation: 1061

Cannot access a closed Stream?

I have just come across an error in my code which opens up the file and reads the rawData.

The error I am getting is as follows:

enter image description here As you can see, I am opening up a Memory Stream but as I do so I am getting an error saying that I cannot access the Stream?

I there a reason why I am not able to access a closed stream?

Code Used:

// Try to decompress the file data.
byte[] rawData = null;

using (MemoryStream zipStream = new MemoryStream(fileData))
{
    if (ZipPackage.IsZipFile(zipStream))
    {
        using (ZipPackage unzipper = ZipPackage.Open(zipStream))
        {
            // The zip package only contains one entry since GeoObject.FileData only contains one shape or POI.
            if (unzipper.ZipPackageEntries.Count > 0)
            {
                StreamReader reader = new StreamReader(unzipper.ZipPackageEntries[0].OpenInputStream());
                rawData = System.Text.Encoding.UTF8.GetBytes(reader.ReadToEnd());
            }
        }
    }
}

Stack

at System.IO.__Error.StreamIsClosed()
at System.IO.MemoryStream.set_Position(Int64 value)
at Telerik.Windows.Zip.ZipPackage.IsZipFile(Stream stream)
at Satmap.Planner.Silverlight.XmlConverters.DBGeoObjectsToFromDBShapes.ExtractRawFileData(GeoObject geoObject, Byte[] fileData)
at Satmap.Planner.Silverlight.DatabaseShapesToFromMapShapes.ConvertDatabaseShapesToMapShapes(GeoObject geoObject, Boolean filter)
at Satmap.Planner.Silverlight.DatabaseShapesToFromMapShapes.ConvertDatabaseShapesToMapShapes(GeoObject geoObject)
at Satmap.Planner.Silverlight.ViewControllers.MainMapViewController.BackgroundWorkerFileLoad_RunWorkerCompleted(Object sender, RunWorkerCompletedEventArgs e)
at System.ComponentModel.BackgroundWorker.OnRunWorkerCompleted(RunWorkerCompletedEventArgs e)
at System.ComponentModel.BackgroundWorker.<OnRun>b__1(Object state) 

New Stack:

at System.IO.MemoryStream.set_Capacity(Int32 value)
at System.IO.MemoryStream.EnsureCapacity(Int32 value)
at System.IO.MemoryStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at System.IO.Stream.InternalCopyTo(Stream destination, Int32 bufferSize)
at System.IO.Stream.CopyTo(Stream destination)
at Telerik.Windows.Zip.ZipArchive.WriteArchive()
at Telerik.Windows.Zip.ZipArchive.Dispose(Boolean disposing)
at Telerik.Windows.Zip.ZipArchive.Dispose()
at Satmap.Planner.Silverlight.XmlConverters.DBGeoObjectsToFromDBShapes.ExtractRawFileData(GeoObject geoObject, Byte[] fileData)
at Satmap.Planner.Silverlight.DatabaseShapesToFromMapShapes.ConvertDatabaseShapesToMapShapes(GeoObject geoObject, Boolean filter)
at Satmap.Planner.Silverlight.DatabaseShapesToFromMapShapes.ConvertDatabaseShapesToMapShapes(GeoObject geoObject)
at Satmap.Planner.Silverlight.ViewControllers.MainMapViewController.BackgroundWorkerFileLoad_RunWorkerCompleted(Object sender, RunWorkerCompletedEventArgs e)
at System.ComponentModel.BackgroundWorker.OnRunWorkerCompleted(RunWorkerCompletedEventArgs e)
at System.ComponentModel.BackgroundWorker.<OnRun>b__1(Object state)

Upvotes: 2

Views: 9367

Answers (1)

Dirk Vollmar
Dirk Vollmar

Reputation: 176159

What you see here is the behavior of the Telerik ZipPackage class. The static IsZipFile method is disposing the stream, probably due to a bug (you may contact Telerik support about this).

However, it probably is not necessary that you first check the validity of the zip package. Simply use try...catch around the relevant pieces of code:

// Try to decompress the file data.
byte[] rawData = null;

using (MemoryStream zipStream = new MemoryStream(fileData))
{
    try
    {
        using (ZipPackage unzipper = ZipPackage.Open(zipStream))
        {
            // The zip package only contains one entry since GeoObject.FileData only contains one shape or POI.
            if (unzipper.ZipPackageEntries.Count > 0)
            {
                StreamReader reader = new StreamReader(unzipper.ZipPackageEntries[0].OpenInputStream());
                rawData = System.Text.Encoding.UTF8.GetBytes(reader.ReadToEnd());
            }
        }
    }
    catch (Exception ex)
    {
         // ZipPackage throws an exception of type Exception if the 
         // package is not valid. Handle exception here, e.g. log etc
    }
}

Update

Telerik's ZipArchive class seems a strange beast. If you are on .NET 4.5 or later, you might be better off switching to the System.IO.Compression.ZipArchive class. If not, you may be able to work around the problem with the non-expandable memory stream by not creating the memory stream from a fixed array. Instead of new MemoryStream(fileData) you can use:

using (var zipStream = new MemoryStream())
{
    zipStream.Write(fileData, 0, fileData.Length);
    zipStream.Position = 0;

    // continue here
}

Upvotes: 2

Related Questions