C # - StreamReader.ReadLine не работает должным образом! - PullRequest
11 голосов
/ 20 сентября 2009

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

Какой самый простой способ получить этот линейно-ориентированный ридер, как в Java BufferedStreamReader? : S

Ответы [ 4 ]

13 голосов
/ 20 сентября 2009

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

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());
    }
}
5 голосов
/ 20 сентября 2009

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

0 голосов
/ 19 ноября 2016
    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

0 голосов
/ 05 ноября 2010

попробовал это и получил

Не удалось найти тип или имя пространства имен 'Stream' (вам не хватает директивы using или ссылки на сборку?) Не удалось найти тип или имя пространства имен StreamReader (отсутствует директива using или ссылка на сборку?) Не удалось найти тип или имя пространства имен StreamReader (отсутствует директива using или ссылка на сборку?) System.Net.Sockets.Socket не содержит определения GetStream

...