【问题标题】:C# - StreamReader.ReadLine does not work properly!C# - StreamReader.ReadLine 无法正常工作!
【发布时间】:2010-11-29 19:59:09
【问题描述】:

我一直在尝试实现 BufferedStreamReader 在 Java 中所做的事情。我打开了一个套接字流,只想以面向行的方式逐行读取它。

我有以下服务器代码。

while (continueProcess)
        {
            try
            {
                StreamReader reader = new StreamReader(Socket.GetStream(), Encoding.UTF8);
                string command = reader.ReadLine();
                if (command == null)
                    break;

                OnClientExecute(command);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

以及以下客户端代码:

TcpClient tcpClient = new TcpClient();
        try
        {
            tcpClient.Connect("localhost", serverPort);
            StreamWriter writer = new StreamWriter(tcpClient.GetStream(), Encoding.UTF8);
            writer.AutoFlush = true;
            writer.WriteLine("login>user,pass");
            writer.WriteLine("print>param1,param2,param3");
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
        finally
        {
            tcpClient.Close();
        }

服务器只读取第一行 (login>user,pass),然后 ReadLine 返回 null!

在 Java 的BufferedStreamReader 中实现这种面向行的阅读器的最简单方法是什么? :s

【问题讨论】:

  • 请在此处处理您的对象(StreamReader 和 StreamWriter)。否则你可能会遇到意想不到的问题。只需在它们周围放置一个 using 块(如 using (StreamWriter writer = ...) { } ),您就可以了
  • 与问题无关——只是一个建议。

标签: c# .net readline streamreader bufferedstream


【解决方案1】:

典型的行阅读器是这样的:

using(StreamReader reader = new StreamReader(Socket.GetStream(), Encoding.UTF8)) {
    string line;
    while((line = reader.ReadLine()) != null) {
        // do something with line
    }
}

(注意using 以确保我们Dispose() 它即使我们得到一个错误和循环)

如果你愿意,你可以用一个迭代器块来抽象这个(关注点分离):

static IEnumerable<string> ReadLines(Stream source, Encoding encoding) {
    using(StreamReader reader = new StreamReader(source, encoding)) {
        string line;
        while((line = reader.ReadLine()) != null) {
            yield return line;
        }
    }
}

(请注意,我们已将其移至函数中并删除了“做某事”,将其替换为“yield return”,从而创建了一个迭代器(一个延迟迭代的非缓冲状态机)

然后我们会像这样简单地使用它:

foreach(string line in ReadLines(Socket.GetStream(), Encoding.UTF8)) {
    // do something with line
}

现在我们的处理代码不需要担心如何读取行 - 只需给定一系列行,对它们做一些事情。

注意using (Dispose()) 也适用于TcpClient;你应该养成检查IDisposable的习惯;例如(仍然包括您的错误记录):

using(TcpClient tcpClient = new TcpClient()) {
    try {
       tcpClient.Connect("localhost", serverPort);
       StreamWriter writer = new StreamWriter(tcpClient.GetStream(), Encoding.UTF8);
       writer.AutoFlush = true;
       writer.WriteLine("login>user,pass");
       writer.WriteLine("print>param1,param2,param3");
    } catch (Exception ex) {
        Console.Error.WriteLine(ex.ToString());
    }
}

【讨论】:

  • 当我使用 StreamReader 从套接字读取时,我发现客户端程序卡住了,在 ReadLine() 方法中花费了无限的时间,最后读取失败。
  • @MasudRahman 这通常意味着:服务器没有发送完整的行(即你要求它等待服务器没有理由发送给你的东西),或者服务器忘记刷新输出缓冲区。您可以添加读取超时,但最终它无法使服务器发送数据。您当然可以自己进行读取和缓冲,但这只会改变问题的性质 - 然后您的工作就是确定在一段时间后没有发送完整的行。
【解决方案2】:

服务器代码中的 while 设置为每个连接仅读取一行。在尝试读取所有正在发送的行期间,您将需要另一个时间。我认为一旦在客户端设置了该流,它将发送所有数据。然后在服务器端,您的流实际上只从该特定流中读取一行。

【讨论】:

  • 在将我的服务器和客户端代码更改为如下服务器后:使用 (StreamReader reader = new StreamReader(Socket.GetStream(), Encoding.UTF8)) { while (continueProcess) .... client: . .. 线程.Sleep(10000); writer.WriteLine("打印>测试,一,二");我将 Thread.Sleep(10000) 插入到我的客户端代码中,服务器开始抛出异常。客户端套接字将一直打开,直到客户端退出,并且由于客户端将在其整个生命周期内发送数据,因此该代码似乎会抛出错误。你不这么认为吗?
  • 没有看到新代码或新异常是什么,我不确定问题可能是什么。
【解决方案3】:
    public string READS()
    {
        byte[] buf = new byte[CLI.Available];//set buffer
        CLI.Receive(buf);//read bytes from stream
        string line = UTF8Encoding.UTF8.GetString(buf);//get string from bytes
        return line;//return string from bytes
    }
    public void WRITES(string text)
    {
        byte[] buf = UTF8Encoding.UTF8.GetBytes(text);//get bytes of text
        CLI.Send(buf);//send bytes
    }

CLI 是一个套接字。 对于某些重新分区,TcpClient 类不再在我的电脑上正常工作, 但是 Socket 类工作得很好。

UTF-8 是搁浅的 StreamReader / Writer Encoding

【讨论】:

    【解决方案4】:

    试了下

    找不到类型或命名空间名称“Stream”(您是否缺少 using 指令或程序集引用?) 找不到类型或命名空间名称“StreamReader”(您是否缺少 using 指令或程序集引用?) 找不到类型或命名空间名称“StreamReader”(您是否缺少 using 指令或程序集引用?) “System.Net.Sockets.Socket”不包含“GetStream”的定义

    【讨论】:

      猜你喜欢
      • 2011-08-31
      • 2020-08-01
      • 2013-08-26
      • 2015-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多