C# - StreamReader.ReadLine не работает должным образом!

просто я пытался реализовать то, что 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

4 ответов


типичный считыватель строк-это что-то вроде:

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", который создает итератор (лениво повторяемое состояние без буферизации машина)

мы бы тогда потребляли это так же просто, как:

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

в то время как в вашем коде сервера настроено только чтение одной строки на соединение. Вам понадобится еще одно время в попытке прочитать все отправляемые строки. Я думаю, что как только этот поток будет настроен на стороне клиента, он отправит все данные. Затем на стороне сервера ваш поток эффективно считывает только одну строку из этого конкретного потока.


попытался это и получил

не удалось найти тип или имя пространства имен "поток" (отсутствует директива using или ссылка на сборку?) Не удалось найти тип или имя пространства имен "StreamReader" (отсутствует директива using или ссылка на сборку?) Не удалось найти тип или имя пространства имен "StreamReader" (отсутствует директива using или ссылка на сборку?) - Система.Сеть.Розетки.Сокет "не содержит определения для "GetStream"


    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-это сокет. для некоторых rezone класс TcpClient больше не работает прямо на моем компьютере, но класс Socket работает просто отлично.

UTF-8-это многожильная кодировка StreamReader / Writer