C#: Using StreamReader to read line from txt file,

2020-02-29 02:11发布

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)

标签: c# peek
5条回答
萌系小妹纸
2楼-- · 2020-02-29 02:36

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楼-- · 2020-02-29 02:37

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;
    }
}
查看更多
\"骚年 ilove
4楼-- · 2020-02-29 02:48

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楼-- · 2020-02-29 02:51

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
            }
查看更多
我只想做你的唯一
6楼-- · 2020-02-29 03:02

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?

查看更多
登录 后发表回答