简体   繁体   English

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

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

I use Peek() method of StreamReader to check whether there are more lines need to be processed. 我使用StreamReader的Peek()方法来检查是否需要处理更多行。 There are more than 1000 lines in my file, but Peek() suddenly return -1 when it reachs line#750. 我的文件中有超过1000行,但Peek()在到达#750行时突然返回-1。 I checked but seems no differences between line#750 and #751. 我查了一下,但#750和#751之间似乎没有区别。 Even I deleted line#750 and 751, it will still break up at other line. 即使我删除了#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)

While it doesn't explain what's going on, I'd personally avoid using Peek . 虽然它没有解释发生了什么,但我个人避免使用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. 您还可以编写一个方法来从TextReader (或从Func<TextReader>或文件名)创建IEnumerable<string> ,这可以使所有这些更加愉快。 If you're just reading a file and you're using .NET 4, then File.ReadLines is already built-in. 如果您只是在阅读文件并且使用的是.NET 4,则File.ReadLines已经内置。

EDIT: Here's one reason you may be getting -1, from the docs of StreamReader.Peek : 编辑:这是您从StreamReader.Peek的文档获得-1的一个原因:

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。

Does your stream support seeking? 你的流是否支持寻求?

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: 我不确定为什么Peek方法在你的情况下返回-1,但通常使用StreamReader类读取行到文件末尾的方法是重复调用ReadLine方法直到返回null

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

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
            }

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: 如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 . Peek方法返回一个整数值,以确定是否发生了文件末尾或其他错误 This allows a user to first check if the returned value is -1 before casting it to a Char type. 这允许用户在将其转换为Char类型之前首先检查返回值是否为-1。

Maybe check for wrong data conversions in your SQL command, I think this method should work too! 也许在SQL命令中检查错误的数据转换,我认为这个方法也应该有效!

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. 当遇到时髦的字符(unicode字符?)时,Peek()会返回-1,而ReadLine()也不可靠,最终会锁定我的应用程序,因为它似乎是标准流未关闭的过程。

Using the Read() method was the only way I could assure I got ALL lines and characters. 使用Read()方法是我能确保获得所有行和字符的唯一方法。 Additionally, using the Process' ErrorDataReceived or OutputDataReceived event handlers also proved UNRELIABLE (missing lines). 此外,使用Process的ErrorDataReceived或OutputDataReceived事件处理程序也证明了UNRELIABLE(缺少行)。 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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM