atconway
atconway

Reputation: 21304

Looping through a text file using StreamReader causes a "Cannot access a disposed object."

I have the following basic code to read a text file from a StreamReader:

Using sr As New StreamReader(FileData)
  Dim line As String = String.Empty
  Do
    'Error occurs on the next line after looping 
    'past the *last* line in the file...sometimes
    line = sr.ReadLine()
    'Some code here to parse and process the line
  Loop Until (line Is Nothing) OrElse (line = String.Empty)
End Using

I tried changing the Do Loop to Do While Not sr.EndOfStream I tried checking If sr.ReadLine IsNot Nothing and a few other things but I keep getting the Cannot access a disposed object. Object name: 'SslStream' error after all 105 lines have successfully been read and processed. This code has been working for a couple of years, but there seems to be some issue with certain files (recently) that is causing this problem.

I opened the file and I didn't see anything out of the ordinary. No extra blank lines, funny characters or anything of the like. Just a normal file with 105 properly formatted lines. So even know there is something about this file causing the error, I need to obviosly handle this programatically.

What can I do to prevent the sr.ReadLine() line of code from throwing that exception that I have not yet tried?

UPDATE Upon reading the last line of the file, the 'EndOfStream' property on the StreamReader goes immdeatly to: EndOfStream: {"Cannot access a disposed object. Object name: 'SslStream'."} It never toggles to 'True'. This makes checking for this condition problematic.

I think I have figured out why this issue only occurs sometimes: if I add in a blank line to the file at the end, none of this ever occurs. It is only when the last line of the file contains data. Still, I should be able to handle this programatically. Telling the vendor supplying the file to always add a blank line at the end should not be the solution.

Upvotes: 1

Views: 5623

Answers (2)

atconway
atconway

Reputation: 21304

Finally - I got this one figured out. Some of the comments from my OP started make me look at this from a different angle. The underlying stream was automatically being closed. I started shifiting focus to the Stream object being loaded into the StreamReader rather than the StreamReader itself.

Turns out the Stream was the culprit. The stream object has a .CanRead property which is 'True' until reading the last line of the file when it turns to 'False'. This was causing the StreamReader.EndOfStream value to be an exception when there were no blank lines in the file.

Checking the value of .CanRead on the underlying Stream which was loaded into the StreamReader and making sure it is not False was the solution. The new loop is below and I made sure to use the short-circuit 'OrElse' or the latter condition would thrown an exception as before.

Using sr As New StreamReader(FileData)   
  Dim line As String = String.Empty   
  Do         
    line = sr.ReadLine()     
    'Some code here to parse and process the line   
  Loop Until (Not FileData.CanRead) OrElse (sr.EndOfStream) 
End Using

Upvotes: 5

Maarten Kesselaers
Maarten Kesselaers

Reputation: 1251

EDIT : Based on the new information, I think the following is your solution. You have to declare a string-object outside of your Do While-loop. During initialisation, fill it for a first time with sr.ReadLine. The rest should be self-explanatory, I guess

Do While (Not line Is Nothing)
    ' Display to console.
    Console.WriteLine(line)
    ' Read in the next line.
    line = sr.ReadLine
Loop

Upvotes: 0

Related Questions