Reputation: 2247
I'm having some trouble using a MemoryStream
We're using a 3rd party spreadsheet component (similar to excel), and I'm trying to save the data as html which they support through the SaveHtml
method below. Seems very simple based on their documentation. Here is my code:
using (var memoryStream = new MemoryStream())
{
this.ActiveSheet.SaveHtml(memoryStream);
memoryStream.Position = 0;
using (var streamReader = new StreamReader(memoryStream))
{
var htmlData = streamReader.ReadToEnd();
}
}
I get an exception when I set the memoryStream.Position = 0
:
System.ObjectDisposedException: Cannot access a closed Stream.
A quick look at their SaveHtml method in Reflector shows the following relevant lines:
public void SaveHtml(Stream stream)
{
StreamWriter writer = null;
try
{
writer = new StreamWriter(stream) { AutoFlush = true };
writer.Write(str);
}
finally
{
if (writer != null)
{
writer.Close();
}
}
}
I'm guessing because the streamWriter is closed by their code, we're out of luck. Closing the streamWriter, closes the underlying Stream, right?
Any way to get around this?
Thanks.
Upvotes: 5
Views: 5392
Reputation: 134
Alternative memory stream implementation can be used in such context:
var stream = new ChunkedStream(pool, asOutputStreamOnDispose: true);
using (var writer = new StreamWriter(stream))
{
writer.Write("hello world");
}
Assert.AreEqual(0, stream.Position);
Assert.AreEqual(ChunkedStreamState.ReadForward, stream.State);
Assert.AreEqual(3, pool.TotalAllocated);
using (var reader = new StreamReader(stream))
{
Assert.AreEqual("hello world", reader.ReadToEnd());
Assert.AreEqual(0, pool.TotalAllocated);
}
Assert.AreEqual(ChunkedStreamState.Closed, stream.State);
Upvotes: 0
Reputation: 1839
It seems it works, so you can create another memory stream. No bytes are copied when extracting the buffer.
using (var memoryStream = new MemoryStream()) {
this.ActiveSheet.SaveHtml(memoryStream);
var buffer = memoryStream.GetBuffer();
using (var memoryStream2 = new MemoryStream(buffer))
using (var streamReader = new StreamReader(memoryStream2)) {
var htmlData = streamReader.ReadToEnd();
}
}
Or you can roll out your own uncloseable MemoryStream and feed it to SaveHtml. This will also prevent disposing it, since Dispose just calls Close. Again, imho:
class MemoryStream2 : MemoryStream {
public override void Close() { }
}
Upvotes: 6