C # - StreamReader.ReadLine не работает должным образом!
-
11-09-2019 - |
Вопрос
Просто я пытался реализовать то, что 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
Решение
Типичный читатель строк - это что-то вроде:
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;
}
}
}
(обратите внимание, что мы переместили это в функцию и удалили "do something", заменив его на "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());
}
}
Другие советы
Параметр while в коде вашего сервера настроен на чтение только одной строки для каждого соединения.Вам понадобится еще одно время в течение попытки, чтобы прочитать все отправляемые строки.Я думаю, как только этот поток будет настроен на стороне клиента, он отправит все данные.Затем на стороне сервера ваш поток фактически считывает только одну строку из этого конкретного потока.
Попробовал это и получил
Не удалось найти тип или имя пространства имен 'Stream' (вам не хватает директивы using или ссылки на сборку?) Не удалось найти тип или имя пространства имен 'StreamReader' (вам не хватает директивы using или ссылки на сборку?) Не удалось найти тип или имя пространства имен 'StreamReader' (вам не хватает директивы using или ссылки на сборку?) 'System.Net.Sockets.Сокет' не содержит определения для '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 - это сокет.в какой-то новой зоне класс TcpClient больше не работает на моем компьютере, но класс Socket работает просто отлично.
UTF-8 - это многожильная кодировка StreamReader / Writer