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

喜你入骨 提交于 2019-12-05 02:57:15

问题


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)


回答1:


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?




回答2:


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);
}



回答3:


Do you need to use peek? Are you skipping certain lines? If you want to read all lines use this.

       while(!sr.EndOfStream)
            {
                //Do stuff
            }



回答4:


As stated in MSDN, Peek Method not only returns -1 when you reach the end of the stream, but also in case of internal errors:

The Peek method returns an integer value in order to determine whether the end of the file, or another error has occurred. This allows a user to first check if the returned value is -1 before casting it to a Char type.

Maybe check for wrong data conversions in your SQL command, I think this method should work too!




回答5:


I ran into a similar problem when trying to interact with an application that required authentication. Peek() would return -1 when encountering funky characters (unicode characters?) and ReadLine() was also unreliable and would eventually lockup my application since it seems the process' Standard stream was not closed.

Using the Read() method was the only way I could assure I got ALL lines and characters. Additionally, using the Process' ErrorDataReceived or OutputDataReceived event handlers also proved UNRELIABLE (missing lines). Below is how I solved my problem and insured all lines, and characters, were received:

process.Start();
var stdOutput = process.StandardOutput;
StringBuilder fullMessage = new StringBuilder();
while (true)
{
    var character = (char)stdOutput.Read();
    fullMessage.Append(character);

    //Print Out All Characters
    Console.Write(character);
    if (fullMessage.ToString().EndsWith("Enter Password: "))
    {
        //Submit Password To Application
        using(StreamWriter writer = process.StandardInput){
            writer.Write("somepassword");
            writer.Flush();
        }

        break;
    }
}


来源:https://stackoverflow.com/questions/9376887/c-using-streamreader-to-read-line-from-txt-file-but-peek-return-1-even-the

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!