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

发布于 2025-01-07 14:40:25 字数 1146 浏览 1 评论 0原文

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

以下是我的代码供您参考:

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

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

最后我通过使用解决了这个问题: while (stream.CanRead && (x = reader.ReadLine()) != null)

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

追风人 2025-01-14 14:40:25

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

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

这样你就只能在一个地方阅读。不知何故,这比检查你是否可以阅读然后阅读更理智。

您还可以编写一个方法来从 TextReader(或从 Func 或文件名)创建 IEnumerable这可以让这一切变得更加愉快。如果您只是读取文件并且使用 .NET 4,则 < code>File.ReadLines 已内置。

编辑:这是您可能得到 -1 的原因之一,来自 StreamReader.Peek

一个整数,表示要读取的下一个字符,如果没有要读取的字符或流不支持查找,则为 -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?

月寒剑心 2025-01-14 14:40:25

我不确定为什么 Peek Method 返回-1 在你的情况下,但通常的方法是使用 读取行流阅读器类到文件末尾就是重复调用ReadLine 方法 直到返回 null

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

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);
}
梦回旧景 2025-01-14 14:40:25

需要用peek吗?您是否跳过某些行?如果你想读取所有行,请使用它。

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

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
            }
活雷疯 2025-01-14 14:40:25

正如MSDN中所述,Peek方法不仅当到达流末尾时返回 -1,但在出现内部错误时也会返回 -1:

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

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

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!

悟红尘 2025-01-14 14:40:25

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

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

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;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文