问题
How can I send a multiline string with blank lines over a NamedPipe?
If I send a string
string text= @"line 1
line2
line four
";
StreamWriter sw = new StreamWriter(client);
sw.Write(text);
I get on the server side only "line 1":
StreamReader sr = new StreamReader(server);
string message = sr.ReadLine();
When I try something like this
StringBuilder message = new StringBuilder();
string line;
while ((line = sr.ReadLine()) != null)
{
message.Append(line + Environment.NewLine);
}
It hangs in the loop while the client is connected and only releases when the client disconnects.
Any ideas how I can get the whole string without hanging in this loop? I need to to process the string and return it on the same way to the client.
It's important that I keep the original formatting of the string including blank lines and whitespace.
回答1:
StreamReader
is a line-oriented reader. It will read the first line (terminated by a newline). If you want the rest of the text, you have to issue multiple readlines. That is:
StreamReader sr = new StreamReader(server);
string message = sr.ReadLine(); // will get "line1"
string message2 = sr.ReadLine(); // will get "line2"
You don't want to "read to end" on a network stream, because that's going to hang the reader until the server closes the connection. That might be a very long time and could overflow a buffer.
Typically, you'll see this:
NetworkStream stream = CreateNetworkStream(); // however you're creating the stream
using (StreamReader reader = new StreamReader(stream))
{
string line;
while ((line = reader.ReadLine()) != null)
{
// process line received from stream
}
}
That gives you each line as it's received, and will terminate when the server closes the stream.
If you want the reader to process the entire multi-line string as a single entity, you can't reliably do it with StreamReader
. You'll probably want to use a BinaryWriter
on the server and a BinaryReader
on the client.
回答2:
Why not just call ReadToEnd() on StreamReader?
StreamReader sr = new StreamReader(server);
string message = sr.ReadToEnd();
回答3:
I accomplished sending multiple line messages over a named pipe by using token substitution to replace all \r and \n in the message with tokens like {cr} and {lf} thus converting multiple lines messages into 1 line.
Of course, I needed to do the reverse conversion of the receiver side.
The assumption is that the substituted tokens will never be found in the source text.
You can make sure that this happens by also substituting all "{" with {lp}. That way the "{" becomes your escape character.
You can use Regex to make these Replacements.
That worked great and allowed me to use StreamReader.
来源:https://stackoverflow.com/questions/4412686/sending-a-multiline-string-over-namedpipe