11

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)のみを読み取り、 ReadLinenull を返します。

Java のような行指向のリーダーを実現する最も簡単な方法は何BufferedStreamReaderですか? :s

4

4 に答える 4

16

典型的なラインリーダーは次のようなものです:

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());
    }
}
于 2009-09-20T07:16:09.710 に答える
5

サーバー コードの while は、接続ごとに 1 行だけを読み取るように設定されています。送信されているすべての行を読み取る試行中に、別の行が必要になります。そのストリームがクライアント側でセットアップされると、すべてのデータが送信されると思います。サーバー側では、ストリームは事実上、その特定のストリームから 1 行しか読み取っていません。

于 2009-09-20T03:58:11.973 に答える
0
    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 クラスが私の PC で正しく動作しなくなりましたが、Socket クラスは正常に動作します。

UTF-8 は取り残された StreamReader / Writer エンコーディングです

于 2016-11-19T10:23:27.477 に答える
-2

これを試して得た

型または名前空間名 'Stream' が見つかりませんでした (using ディレクティブまたはアセンブリ参照がありませんか?) 型または名前空間名 'StreamReader' が見つかりませんでした (using ディレクティブまたはアセンブリ参照がありませんか?)型または名前空間名 'StreamReader' が見つかりませんでした (using ディレクティブまたはアセンブリ参照がありませんか?) 'System.Net.Sockets.Socket' には 'GetStream' の定義が含まれていません

于 2010-11-05T14:04:42.500 に答える