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
How to Iterate Through the Following Json Using C#
How to Store List of Data from Database to Arraylist or List in C#
Validate Indian Phone Number With Optional +91 or 0 Preceeding 10 Digits
How to Convert English Digits to Arabic Digits
How to Make Xmlserializer Ignore the Namespace on Deserialization
Cast Class into Another Class or Convert Class to Another
Rendering Views from External Assemblies in Mvc6
Response to Preflight Request Doesn't Pass Access Control Check (Angular2)
Deserialize Multiple Xml Elements With the Same Name Through Xmlserializer Class in C#
How to Remove Time Portion of Date in C# in Datetime Object Only
How to Check If a Datetime Value Is Empty or Not in a Put Request
C# Replace Item in List<String> "/"
How to Encrypt a Password Within Appsettings.Json for ASP.NET Core 2
Passing Datetimeoffset as Webapi Query String
How to Show Alert Message in MVC 4 Controller
Reportviewer: Show Reports in Print Layout With Page Width Zoommode
Ssh.Net Sftp Get a List of Directories and Files Recursively
How to Download File With ASP.NET on Buttton'S Onclick Event