72

I don't know too much about streams in C#. Right now I have a stream that I put into a stream reader and read it. Later on in some other method I need to read the stream(same stream object) but this time I get this error

System.ArgumentException was unhandled by user code
  Message="Stream was not readable."
  Source="mscorlib"
  StackTrace:
       at System.IO.StreamReader..ctor(Stream stream, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize)
       at System.IO.StreamReader..ctor(Stream stream)
       at ExtractTitle(Stream file) in :line 33
       at GrabWebPage(String webPath) in :line 62
       at lambda_method(ExecutionScope , ControllerBase , Object[] )
       at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
       at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
       at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
       at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassa.<InvokeActionMethodWithFilters>b__7()
       at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
  InnerException: 

So I am thinking maybe by reading the stream it goes to the end. Then when I try to read it again it is at the end of the stream and thats why I am getting this error.

So can anyone shed some light on this?

Thanks

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
chobo2
  • 83,322
  • 195
  • 530
  • 832

3 Answers3

114

When you read a stream to the end, specifically with StreamReader's ReadToEnd method, you have to Seek it back to the beginning. This can be done like so:

StreamReader sr = new StreamReader(stream);
sr.ReadToEnd();
stream.Seek(0, SeekOrigin.Begin); //StreamReader doesn't have the Seek method, stream does.
sr.ReadToEnd(); // This now works
David X
  • 3,998
  • 3
  • 29
  • 32
45

Your conclusion is correct; once you've reached the end of your stream, you won't be able to read more data until you've reset your position within the stream:

myStream.Position = 0;

This is equivalent to seeking back to the beginning. Note that your stream must support seeking for this to work; not all streams do. You can check this with the CanSeek property.

Michael Petrotta
  • 59,888
  • 27
  • 145
  • 179
  • Well how can I get a stream that does? Like I am trying to "GetResponseStream()" back from an ftp request and this returns a "Stream" this does not support "Seeking" so what should I do? – chobo2 Nov 17 '09 at 02:08
  • Can you read the entire stream in one go? If so, read it into a byte array, then create a new MemoryStream (which supports seeking) from that array. – Michael Petrotta Nov 17 '09 at 02:13
  • How can I read it into a byte array? Like won't I need to figure out the size of the stream first to know how to big to make the byte array? – chobo2 Nov 17 '09 at 02:57
  • Read it in small chunks (say, 1024 bytes), and write that chunk to the MemoryStream. Jon Skeet's wrote a good answer about this: http://stackoverflow.com/questions/221925/creating-a-byte-array-from-a-stream – Michael Petrotta Nov 17 '09 at 03:05
  • A more elegant approach IMO. – Shocked Dec 29 '15 at 21:16
  • It doesn't always work, for example with `System.IO.Packaging.ZipWrappingStream` I get `NotSupportedException` – radrow Oct 29 '21 at 08:16
5

Use BaseStream for StreamReader:

 StreamReader sr = new StreamReader(pFileStream);
 sr.BaseStream.Seek(0, SeekOrigin.Begin);
m.cekiera
  • 5,365
  • 5
  • 21
  • 35
Glaucio BP
  • 51
  • 1
  • 2