C# - StreamReader.ReadLine 不能正常工作!

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1450263/
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-06 17:39:30  来源:igfitidea点击:

C# - StreamReader.ReadLine does not work properly!

c#.netreadlinestreamreaderbufferedstream

提问by Aleyna

Simply I have been trying to implement what BufferedStreamReaderdoes in Java. I have a socket stream open and just want to read it in a line-oriented fashion - line by line.

只是我一直在尝试实现BufferedStreamReaderJava 中的功能。我打开了一个套接字流,只想以面向行的方式逐行读取它。

I have the following server-code.

我有以下服务器代码。

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

And the following client-code:

以及以下客户端代码:

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

The server reads only the very first line (login>user,pass) and then ReadLinereturns null!

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

What's the easiest way of achieving this line-oriented reader as it is in Java's BufferedStreamReader? :s

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

采纳答案by Marc Gravell

A typical line-reader is something like:

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

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

(note the usingto ensure we Dispose()it even if we get an error, and the loop)

(注意即使我们得到错误也using能确保我们Dispose()这样做,以及循环)

If you want, you could abstract this (separation of concerns) with an iterator block:

如果需要,您可以使用迭代器块对此进行抽象(关注点分离):

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

(note we've moved this into a function and removed the "do something", replacing it with "yield return", which creates an iterator (a lazily iterated, non-buffering state machine)

(注意我们已经把它移到一个函数中并删除了“做某事”,用“收益回报”代替它,这会创建一个迭代器(一个懒惰迭代的非缓冲状态机)

We would then consume this as simply as:

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

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

Now our processing code doesn't need to worry about howto read lines - simply givena sequence of lines, do something with them.

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

Note that the using(Dispose()) applies to TcpClienttoo; you should make a habit of checking for IDisposable; for example (still including your error-logging):

请注意,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());
    }
}

回答by LJM

The while in your server code is setup to only read one line per connection. You'll need another while within the try to read all of the lines being sent. I think once that stream is setup on the client side, it is going to send all of the data. Then on the server side, your stream is effectively only reading one line from that particular stream.

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

回答by Gerald Connolly

Tried this and got

试过这个并得到

The type or namespace name 'Stream' could not be found (are you missing a using directive or an assembly reference?) The type or namespace name 'StreamReader' could not be found (are you missing a using directive or an assembly reference?) The type or namespace name 'StreamReader' could not be found (are you missing a using directive or an assembly reference?) 'System.Net.Sockets.Socket' does not contain a definition for 'GetStream'

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

回答by Bailey Drahoss

    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 is a socket. for some rezone the TcpClient class doesn't work right on my pc any more, but the Socket class works just fine.

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

UTF-8 is the stranded StreamReader / Writer Encoding

UTF-8 是搁浅的 StreamReader / Writer 编码