Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#: Using StreamReader to read line from txt file, but Peek() return -1 even there are a lot of lines left

Tags:

c#

peek

I use Peek() method of StreamReader to check whether there are more lines need to be processed. There are more than 1000 lines in my file, but Peek() suddenly return -1 when it reachs line#750. I checked but seems no differences between line#750 and #751. Even I deleted line#750 and 751, it will still break up at other line.

Below are my codes for your information:

try
{
    String ftpserver = ftp + filename;
    reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpserver));
    reqFTP.UsePassive = false;
    reqFTP.UseBinary = true;
    reqFTP.Proxy = null;
    reqFTP.Credentials = new NetworkCredential(username, password);

    reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
    response = (FtpWebResponse)reqFTP.GetResponse();
    stream = response.GetResponseStream();
    reader = new StreamReader(stream, ConfigHelper.MyEncoding);
    while (reader.Peek() > -1)
    {
        string x = reader.ReadLine();
        if (x != null)
        {
          //.......
         }
    }
}
catch (Exception ex)
{
}
finally
{
    if (reader != null)
        reader.Close();
    if (response != null)
        response.Close();
}

I tried while ((x = reader.ReadLine()) != null), but an exception of "Cannot access a disposed object" was thrown out.

Finally I figured it out by using: while (stream.CanRead && (x = reader.ReadLine()) != null)

like image 739
Alan Avatar asked Feb 21 '12 11:02

Alan


2 Answers

While it doesn't explain what's going on, I'd personally avoid using Peek. I'd use:

string line;
while ((line = reader.ReadLine()) != null)
{
    // Use the line
}

That way you're only reading in one place. It somehow feels more sane than checking whether or not you can read, and then reading.

You can also write a method to create an IEnumerable<string> from a TextReader (or from a Func<TextReader>, or a filename) which can make all of this more pleasant. If you're just reading a file and you're using .NET 4, then File.ReadLines is already built-in.

EDIT: Here's one reason you may be getting -1, from the docs of StreamReader.Peek:

An integer representing the next character to be read, or -1 if there are no characters to be read or if the stream does not support seeking.

Does your stream support seeking?

like image 196
Jon Skeet Avatar answered Sep 23 '22 22:09

Jon Skeet


I'm not sure why Peek Method returns -1 in your case, but the usual way to read lines with the StreamReader Class to the end of the file is to repeatedly call the ReadLine Method until null is returned:

string line;
while ((line = reader.ReadLine()) != null)
{
    Console.WriteLine(line);
}
like image 32
dtb Avatar answered Sep 25 '22 22:09

dtb