C#:使用 StreamReader 从 txt 文件中读取行,但 Peek() 返回 -1,即使还有很多行

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9376887/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 07:06:16  来源:igfitidea点击:

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

c#peek

提问by Alan

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.

我使用 StreamReader 的 Peek() 方法来检查是否还有更多行需要处理。我的文件中有 1000 多行,但是 Peek() 在到达第 750 行时突然返回 -1。我检查过,但 line#750 和 #751 之间似乎没有区别。即使我删除了第 750 行和 751 行,它仍然会在其他行中断。

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.

我试过了while ((x = reader.ReadLine()) != null),但抛出了“无法访问已处理的对象”的异常。

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

最后我想通了它使用: while (stream.CanRead && (x = reader.ReadLine()) != null)

回答by dtb

I'm not sure why Peek Methodreturns -1 in your case, but the usual way to read lines with the StreamReader Classto the end of the file is to repeatedly call the ReadLine Methoduntil nullis returned:

我不确定为什么Peek 方法在您的情况下返回 -1,但是使用StreamReader 类将行读取到文件末尾的常用方法是重复调用ReadLine 方法,直到null返回:

string line;
while ((line = reader.ReadLine()) != null)
{
    Console.WriteLine(line);
}

回答by Jon Skeet

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

虽然它没有解释发生了什么,但我个人会避免使用Peek. 我会用:

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

That way you're only readingin one place. It somehow feels more sane than checking whether or not you canread, 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.ReadLinesis already built-in.

您还可以编写一种方法来创建一个IEnumerable<string>from a TextReader(或 from aFunc<TextReader>或文件名),这可以使所有这些变得更加愉快。如果您只是在读取文件并且使用 .NET 4,那么 .NET 4File.ReadLines已经是内置的。

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

编辑:这是您可能从以下文档中获得 -1 的原因之一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.

表示要读取的下一个字符的整数,如果没有要读取的字符或流不支持查找,则为 -1。

Doesyour stream support seeking?

您的流是否支持搜索?

回答by David Jazbec

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
            }

回答by MAXE

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

正如 MSDN 中所述,Peek Method不仅在到达流末尾时返回 -1,而且在出现内部错误时也返回:

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.

Peek 方法返回一个整数值以确定是文件结束,还是发生了另一个错误。这允许用户在将其转换为 Char 类型之前首先检查返回值是否为 -1。

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

也许检查您的 SQL 命令中的错误数据转换,我认为这种方法也应该有效!

回答by CaMiX

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.

我在尝试与需要身份验证的应用程序交互时遇到了类似的问题。Peek() 在遇到奇怪的字符(unicode 字符?)时会返回 -1,而 ReadLine() 也不可靠,最终会锁定我的应用程序,因为进程的标准流似乎没有关闭。

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:

使用 Read() 方法是我可以确保获得所有行和字符的唯一方法。此外,使用 Process 的 ErrorDataReceived 或 OutputDataReceived 事件处理程序也证明不可靠(缺少行)。以下是我如何解决我的问题并为所有行和字符投保:

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