Sending a multiline string over NamedPipe? - c#

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.

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.

Why not just call ReadToEnd() on StreamReader?
StreamReader sr = new StreamReader(server);
string message = sr.ReadToEnd();

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.

Related

StreamReader stop program on readLine

I am trying to connect to the server and read data through StreamReader. The ReadLine method stops program execution after the server finishes sending data and starts waiting for a response from the client.
For example:
StreamWriter writer = new StreamWriter(sslStream);
StreamReader reader = new StreamReader(sslStream);
string response;
writer.WriteLine("HI!");
while((response = reader.ReadLine()) != null){
Console.WriteLine(response);
}
Output:
S: somedata1
S: somedata2
S: *no data*
(Program does nothing, no exit codes or thg else)
After that, nothing happens, the debugger does not go further along the lines. Can anyone tell me what the problem is?
Replace
while((response = reader.ReadLine()) != null){
Console.WriteLine(response);
}
with
while(!reader.EndOfStream)
{
string line = reader.ReadLine();
Console.WriteLine(line);
}
It is also good practice to wrap StreamReader and StreamWriter in using block like this:
using (StreamReader reader = new StreamReader(sslStream)) {
// ... your code
}
After using block is finished it will dispose the stream automatically. Do it for all classes that implement IDisposable.

How to read the text from another computer

I have tried to read the file from other computer using the IP address, but i could not able to read that one.It's raised the exception like "Could not find a part of the path 'E:\IPFile_Read\IPFile_Read\bin\Debug\#\IPAddress\Test\News.txt'"
Code:
{
StreamReader sr = new StreamReader("#\\IPaddress\\Test\\News.txt");
line = sr.ReadLine();
while (line != null)
{
text_Data.Text = line;
line = sr.ReadLine();
}
sr.Close();
Console.ReadLine();
}
How can i read the text file from another computer.
"#\\IPaddress\\Test\\News.txt" should be #"\\IPaddress\Test\News.txt". For verbatim strings, the # goes before the opening quote, and if you're using a verbatim string, you don't need to escape the slashes. The UNC prefix still needs the \\, because it really does have two backslashes.

C#: Using StreamReader to read line from txt file, but Peek() return -1 even there are a lot of lines left

I use Peek() method of StreamReader to check whether there are more lines need to be processed. There are more than 1000 lines in my file, but Peek() suddenly return -1 when it reachs line#750. I checked but seems no differences between line#750 and #751. Even I deleted line#750 and 751, it will still break up at other line.
Below are my codes for your information:
try
{
String ftpserver = ftp + filename;
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpserver));
reqFTP.UsePassive = false;
reqFTP.UseBinary = true;
reqFTP.Proxy = null;
reqFTP.Credentials = new NetworkCredential(username, password);
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
response = (FtpWebResponse)reqFTP.GetResponse();
stream = response.GetResponseStream();
reader = new StreamReader(stream, ConfigHelper.MyEncoding);
while (reader.Peek() > -1)
{
string x = reader.ReadLine();
if (x != null)
{
//.......
}
}
}
catch (Exception ex)
{
}
finally
{
if (reader != null)
reader.Close();
if (response != null)
response.Close();
}
I tried while ((x = reader.ReadLine()) != null), but an exception of "Cannot access a disposed object" was thrown out.
Finally I figured it out by using:
while (stream.CanRead && (x = reader.ReadLine()) != null)
While it doesn't explain what's going on, I'd personally avoid using Peek. I'd use:
string line;
while ((line = reader.ReadLine()) != null)
{
// Use the line
}
That way you're only reading in one place. It somehow feels more sane than checking whether or not you can read, and then reading.
You can also write a method to create an IEnumerable<string> from a TextReader (or from a Func<TextReader>, or a filename) which can make all of this more pleasant. If you're just reading a file and you're using .NET 4, then File.ReadLines is already built-in.
EDIT: Here's one reason you may be getting -1, from the docs of StreamReader.Peek:
An integer representing the next character to be read, or -1 if there are no characters to be read or if the stream does not support seeking.
Does your stream support seeking?
I'm not sure why Peek Method returns -1 in your case, but the usual way to read lines with the StreamReader Class to the end of the file is to repeatedly call the ReadLine Method until null is returned:
string line;
while ((line = reader.ReadLine()) != null)
{
Console.WriteLine(line);
}
Do you need to use peek? Are you skipping certain lines? If you want to read all lines use this.
while(!sr.EndOfStream)
{
//Do stuff
}
As stated in MSDN, Peek Method not only returns -1 when you reach the end of the stream, but also in case of internal errors:
The Peek method returns an integer value in order to determine whether the end of the file, or another error has occurred. This allows a user to first check if the returned value is -1 before casting it to a Char type.
Maybe check for wrong data conversions in your SQL command, I think this method should work too!
I ran into a similar problem when trying to interact with an application that required authentication. Peek() would return -1 when encountering funky characters (unicode characters?) and ReadLine() was also unreliable and would eventually lockup my application since it seems the process' Standard stream was not closed.
Using the Read() method was the only way I could assure I got ALL lines and characters. Additionally, using the Process' ErrorDataReceived or OutputDataReceived event handlers also proved UNRELIABLE (missing lines). Below is how I solved my problem and insured all lines, and characters, were received:
process.Start();
var stdOutput = process.StandardOutput;
StringBuilder fullMessage = new StringBuilder();
while (true)
{
var character = (char)stdOutput.Read();
fullMessage.Append(character);
//Print Out All Characters
Console.Write(character);
if (fullMessage.ToString().EndsWith("Enter Password: "))
{
//Submit Password To Application
using(StreamWriter writer = process.StandardInput){
writer.Write("somepassword");
writer.Flush();
}
break;
}
}

StreamReader with TcpClient returning incorrect strings

I am using TcpClient and NetworkStream to initiate a connection to a POP server for authentication. Bad practice, good for learning.
When I Telnet into the POP server, the response produced is initially :
+OK Dovecot Ready
User enters username
+OK
User enters pass which is checked
+OK if valid -N if not
My program is connecting to the POP server, opening a StreamReader and Writer, writing all of this data and checking the response.
using (TcpClient client = new TcpClient("host.university.ie", 110)) {
using (NetworkStream stream = client.GetStream()) {
using (StreamReader reader = new StreamReader(stream)) {
using (StreamWriter writer = new StreamWriter(stream)) {
string response = reader.ReadLine();
writer.Write("USER " + username );
response = reader.ReadLine();
writer.Write("PASS " + password );
string response = reader.ReadLine();
Response.Write(#"<script language='javascript'>alert('The following response as been received: \n" + response + " .');</script>");
isValid = response[ 0 ].Equals('+');
writer.WriteLine("quit\n");
}
}
}
}
}
However, when I enter this code, the query goes into an infinite loop. The confusing thing is that when I reduce the number of calls to reader.ReadLine() to one, it returns "+OK Dovecot Ready"! So it is connecting to the POP server but it will not work after this. Does anyone have any ideas what might be causing this?
No, it isn't an infinite loop. The second call to reader.ReadLine() will never return, because you haven't finished sending the USER command to the server. You must send linefeed characters using .WriteLine instead of .Write
Try this:
writer.WriteLine("USER " + username);
writer.Flush();
and this:
writer.WriteLine("PASS " + password);
writer.Flush();
EDIT: Added calls to .Flush as per spender's suggestion.
In addition to #atornblad's answer, consider writer.Flush() after you write to the stream and need a response.
Try to check: CanWrite and CanRead on the stream and check your encoding:
See: http://msdn.microsoft.com/de-de/library/system.net.sockets.tcpclient.getstream.aspx
Some further questions:
Where is your infinity loop? I can not see any Loops in your code. ReadLine is a blocking method. Maybe the end of line character is the problem? Try Read() instead to get character wise output.
Where does it return "+OK Dovecot Ready"? If it is in your Gui try to call .Refresh on the element that should display the result because your GUI thread my be blocked by the following blocking ReadLine() calls.
Is this \n by purpose?
writer.WriteLine("quit\n");
This leads to an double Line termination.
And try to use
.Flush() after writing to your stream.

Streaming programming

I need to learn more about streaming techniques.
I am using biztalk and want to develop some custom pipelinecomponents.
For performance factors everything has to be in a stream based fashion.
I receive a streamed message, but I want to do some replacements in the text,
what I do now is:
string msg = "";
using(StreamReader r = new StreamReader(stream)){
msg = r.readToEnd();
}
//do replacements
//send stream away
StreamWriter...
As you see I break the stream when I execute r.readToEnd().
How can I edit the message in stream?
thx
You cannot. You can read parts of the message from the stream, replace what you want in each part and finally write processed part to another stream.
Using ReadToEnd is opposite to streaming concept. What I can suggest is that you should use:
using (StreamReader r = new StreamReader(stream))
using (StreamWriter w = new StreamWriter(someOutputStream))
{
string line = null;
while ((line = r.ReadLine()) != null)
{
line = DoReplacements(line);
w.WriteLine(line);
}
}

Categories