C # – StreamReader.ReadLine non funziona correttamente!

Semplicemente ho cercato di implementare ciò che BufferedStreamReader fa in Java. Ho un stream di socket aperto e voglio solo leggerlo in modo orientato alla linea – 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 ) e poi ReadLine restituisce null!

Qual è il modo più semplice per ottenere questo lettore orientato alla linea così come lo è in Java BufferedStreamReader ? :S

    Un tipico lettore di linea è qualcosa del tipo:

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

    (nota l’ using per assicurarci di Dispose() anche se otteniamo un errore e il ciclo)

    Se vuoi, puoi astrarre questo (separazione delle preoccupazioni) con un blocco iteratore:

     static IEnumerable ReadLines(Stream source, Encoding encoding) { using(StreamReader reader = new StreamReader(source, encoding)) { string line; while((line = reader.ReadLine()) != null) { yield return line; } } } 

    (si noti che abbiamo spostato questo in una funzione e rimosso il “do something”, sostituendolo con “yield return”, che crea un iteratore (una macchina a stati non ponderata, lazily iterated)

    Quindi lo consumeremmo semplicemente come:

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

    Ora il nostro codice di elaborazione non ha bisogno di preoccuparsi di come leggere le righe – semplicemente dato una sequenza di linee, fare qualcosa con loro.

    Si noti che l’ using ( Dispose() ) si applica anche a TcpClient ; dovresti prendere l’abitudine di verificare la presenza di IDisposable ; per esempio (includendo 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()); } } 

    Il tempo nel tuo codice server è impostato per leggere solo una riga per connessione. Ne avrai bisogno un altro mentre cerchi di leggere tutte le linee inviate. Penso che una volta che lo stream è configurato dal lato client, invierà tutti i dati. Quindi sul lato server, il tuo stream sta effettivamente leggendo solo una riga da quel particolare stream.

    Ho provato questo e ottenuto

    Non è stato ansible trovare il nome dello spazio dei nomi “Stream” (manca una direttiva using o un riferimento all’assembly?) Imansible trovare il nome dello spazio dei nomi “StreamReader” (manca una direttiva using o un riferimento all’assembly?) Non è stato ansible trovare il nome dello spazio dei nomi ‘StreamReader’ (manca una direttiva using o un riferimento all’assembly?) ‘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 class TcpClient non funziona più sul mio pc, ma la class Socket funziona perfettamente.

    UTF-8 è la codifica StreamReader / Writer a trefoli