Cannot Access a Closed Stream of a Memorystream, How to Reopen

Cannot access a closed Stream of a memoryStream, how to reopen?

How can I reopen a closed memory stream?

You can't reopen the stream. If you need to "reset" the stream, just assign it a new instance:

memoryStream = new MemoryStream();

MemoryStream - Cannot access a closed Stream

This is because the StreamReader closes the underlying stream automatically when being disposed of. The using statement does this automatically.

However, the StreamWriter you're using is still trying to work on the stream (also, the using statement for the writer is now trying to dispose of the StreamWriter, which is then trying to close the stream).

The best way to fix this is: don't use using and don't dispose of the StreamReader and StreamWriter. See this question.

using (var ms = new MemoryStream())
{
var sw = new StreamWriter(ms);
var sr = new StreamReader(ms);

sw.WriteLine("data");
sw.WriteLine("data 2");
ms.Position = 0;

Console.WriteLine(sr.ReadToEnd());
}

If you feel bad about sw and sr being garbage-collected without being disposed of in your code (as recommended), you could do something like that:

StreamWriter sw = null;
StreamReader sr = null;

try
{
using (var ms = new MemoryStream())
{
sw = new StreamWriter(ms);
sr = new StreamReader(ms);

sw.WriteLine("data");
sw.WriteLine("data 2");
ms.Position = 0;

Console.WriteLine(sr.ReadToEnd());
}
}
finally
{
if (sw != null) sw.Dispose();
if (sr != null) sr.Dispose();
}

Cannot access a closed Stream when returning FileStreamResult from C# .NetCore API

Using statements close and unload the variable from memory set in the using statement which is why you are getting an error trying to access a closed memory stream. You don't need to use a using statement if you are just going to return the result at the end.

Using statements are useful for taking care of removing data from memory for you but you could always dispose of the data yourself using .dispose()

Proper way of using memory stream: Cannot access closed stream

I suspect doc.Close() is closing the underlying stream and based on your comments I wonder if you reset the position of the streams. You could try to make another copy of the stream and regard for it's positions.

Example:

protected MemoryStream printSelectionPDF()
{
var output = new MemoryStream();
var doc = new Document(PageSize.A4);
var writer = PdfWriter.GetInstance(doc, output);

string Sur = DropDownListSurname.SelectedValue;
string Cat = DropDownListCategory.SelectedItem.Text;
string Pos = DropDownListPosition.SelectedItem.Text;
string Resp = DropDownListResp.SelectedValue;

doc.SetMargins(36, 36, 18, 18);

GridView1.AllowPaging = false;
GridView1.DataBind();
doc.Open();
CreatePDF(doc, rdBtnStaff.Checked, IncludeHistoricCheckBox.Checked, Sur, Cat, Pos, Resp);

// copying stream
output.Flush();
output.Position = 0;
var copyStream = new MemoryStream();
output.CopyTo(copyStream);
copyStream.Position = 0;
// end copying stream

doc.Close();
GridView1.AllowPaging = true;
return copyStream;
}

Cannot access a closed Stream?

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
}

C# - Cannot access a closed stream

Looking at the source code for the (deprecated) iTextSharp 5.5.13.2 here, I can find the source for the DocWriter (base class of PdfWriter) and it's Close method here

public virtual void Close() {
open = false;
os.Flush();
if (closeStream)
os.Close();
}

os in this case is whatever was passed as the second argument to PdfWriter.GetInstance (ms in your case). Using Ctrl + F I can find the source for closeStream, which happens to be a property exposes as CloseStream here

public virtual bool CloseStream {
get {
return closeStream;
}
set {
closeStream = value;
}
}

And all together Close is automatically called by the Dispose method of DocWriter

public virtual void Dispose() {
Close();
}

So, if you don't want the PdfWriter to close your ms, you'll need to set writer.CloseStream = false; before your PdfWriter gets closed

MemoryStream closed error

You are using the stream twice: once to create the PDF in memory, and a second time to upload it. Reuse of a stream can be problematic when you don't know what happens to it by the abstractions (in this case iTextSharp). Instead, convert the stream to a byte array and create a new stream from the array.

byte[] bytes;

using (MemoryStream ms = new MemoryStream())
{
PdfWriter outputWriter = PdfWriter.GetInstance(newPDF, ms);
newPDF.Open();
PdfContentByte cb1 = outputWriter.DirectContent;

for (int pagesToAddFromSourcePDFToNewPDF = 0; pagesToAddFromSourcePDFToNewPDF < soa_total_pages; pagesToAddFromSourcePDFToNewPDF++)
{
if (pagesToAddFromSourcePDFToNewPDF > 0)
{
currentPageInSourcePDF++;
}

newPDF.NewPage();
PdfImportedPage page = outputWriter.GetImportedPage(sourcePDF, currentPageInSourcePDF);
cb1.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
}

newPDF.Close();

bytes = ms.ToArray();
}

filesCreated++;

using (var ms = new MemoryStream(bytes))
{
// Upload stream to AWS
using (var transferUtility = new TransferUtility(client))
{
transferUtility.Upload(ms, "mybucketname", "1/soa/" + newPDFFilename);
}

}

MemoryStream - Cannot access a closed Stream when merging PDFs

Set CloseStream to false, otherwise the output stream will be closed when you call pCopy.Close().

pCopy = new PdfSmartCopy(doc, msOutput) { CloseStream = false };


Explanation

I found no documentation over the Internet so I had to look at the source code directly.

Here's the declaration of the PdfSmartCopy class:

public class PdfSmartCopy : PdfCopy
{
// ...

public PdfSmartCopy(Document document, Stream os) : base(document, os) {
// ...
}

// ...
}

Here is the declaration of the PdfCopy class:

public class PdfCopy : PdfWriter
{
// ...

public PdfCopy(Document document, Stream os) : base(new PdfDocument(), os) {
// ...
}

// ...
}

The declaration of the PdfWriter class:

public class PdfWriter : DocWriter, 
IPdfViewerPreferences,
IPdfEncryptionSettings,
IPdfVersion,
IPdfDocumentActions,
IPdfPageActions,
IPdfIsoConformance,
IPdfRunDirection,
IPdfAnnotations
{
// ...

protected PdfWriter(PdfDocument document, Stream os) : base(document, os) {
// ...
}

// ...
}

And finally, the declaration of DocWriter class:

public abstract class DocWriter : IDocListener
{
// ...

// default value is true
protected bool closeStream = true;

public virtual bool CloseStream {
get {
return closeStream;
}
set {
closeStream = value;
}
}

protected DocWriter(Document document, Stream os)
{
this.document = document;
this.os = new OutputStreamCounter(os);
}

public virtual void Close() {
open = false;
os.Flush();
if (closeStream) // <-- Take a look at this line
os.Close();
}

// ...
}


Related Topics



Leave a reply



Submit