C# - StreamReader.ReadLine non funziona correttamente!
-
11-09-2019 - |
Domanda
Semplicemente ho cercato di implementare cosa BufferedStreamReader
fa in Java.Ho un socket stream aperto e voglio solo leggerlo in modo orientato alla riga, riga per riga.
Ho il seguente codice server.
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());
}
}
E il seguente codice cliente:
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();
}
Il server legge solo la prima riga (login>user,pass
) poi ReadLine
restituisce null!
Qual è il modo più semplice per ottenere questo lettore orientato alla riga come in Java BufferedStreamReader
?:S
Soluzione
Un tipico lettore di riga è qualcosa del tipo:
using(StreamReader reader = new StreamReader(Socket.GetStream(), Encoding.UTF8)) {
string line;
while((line = reader.ReadLine()) != null) {
// do something with line
}
}
(notare la using
per garantire noi Dispose()
anche se riceviamo un errore e il ciclo)
Se vuoi, puoi astrarre questo (separazione delle preoccupazioni) con un blocco iteratore:
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;
}
}
}
(nota che lo abbiamo spostato in una funzione e rimosso "fai qualcosa", sostituendolo con "yield return", che crea un iteratore (una macchina a stati iterata pigramente e senza buffering)
Lo consumeremmo quindi semplicemente come:
foreach(string line in ReadLines(Socket.GetStream(), Encoding.UTF8)) {
// do something with line
}
Ora il nostro codice di elaborazione non deve preoccuparsi Come leggere le righe - semplicemente dato una sequenza di righe, fai qualcosa con esse.
Si noti che il using
(Dispose()
) si applica a TcpClient
pure;dovresti prendere l'abitudine di controllare IDisposable
;ad esempio (inclusa ancora la registrazione degli errori):
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());
}
}
Altri suggerimenti
La mentre nel codice del server è configurato per leggere una sola riga per ogni connessione. Avrete bisogno di un altro, mentre all'interno della provare a leggere tutte le linee di essere inviato. Penso che una volta che il flusso è installato sul lato client, si sta per inviare tutti i dati. Poi sul lato server, il tuo stream è efficace solo la lettura di una riga da quel particolare flusso.
provato questo e ha ottenuto
Il tipo o dello spazio dei nomi il nome 'flusso' non è stato trovato (che le manca un un riferimento all'assembly direttiva using o?) Il tipo o dello spazio dei nomi il nome 'StreamReader' non è stato trovato (che le manca un un riferimento all'assembly direttiva using o?) Il tipo o dello spazio dei nomi il nome 'StreamReader' non è stato trovato (che le manca un un riferimento all'assembly direttiva using o?) 'System.Net.Sockets.Socket' non contiene una definizione per '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 è una presa. per alcuni Rezone la classe TcpClient non funziona bene sul mio pc più, ma la classe Socket funziona bene.
UTF-8 è lo StreamReader / scrittura codifica stranded