tags:

views:

508

answers:

6

How can I read from a stream when I don't know in advance how much data will come in? Right now I just picked a number on a high side (as in code below), but there's no guarantee I won't get more than that.

So I read a byte at a time in a loop, resizing array each time? Sounds like too much resizing to be done :-/

TcpClient tcpclnt = new TcpClient();
tcpclnt.Connect(ip, port);

Stream stm = tcpclnt.GetStream();

stm.Write(cmdBuffer, 0, cmdBuffer.Length);

byte[] response = new Byte[2048];
int read = stm.Read(response, 0, 2048);

tcpclnt.Close();
+1  A: 
int count;
while ( (count = stm.Read(buffer, 0, buffer.Length)) > 0 ) {
   // process buffer[0..count-1]
   // sample:
   // memoryStream.Write(buffer, 0, count);
}
Mehrdad Afshari
A: 

Code:

byte[] buffer = new byte[1024];
int amt = 0;
while((amt = stm.Read(buffer, 0, 1024) != 0)
{
   // do something
}

depends a bit on what you are receving, if just plain text you could store it in a stringbuilder, if large amounts of binary data, store it in say a memorystream

Fredrik Leijon
hm, my code field failed :)
Fredrik Leijon
Fixed. Shame I can't leave comment under 15 characters, I said everything I needed by char 7.
GWLlosa
+6  A: 

MemoryStream is your friend

http://msdn.microsoft.com/en-us/library/system.io.memorystream

Construct with no default size and it will autoresize. Then just loop as you suggest reading a reasonable amount of data each time. I usually pick at minimum the MTU as the default buffer size.

To get the underlying byte[] array that it creates call

memoryStreamInstance.GetBuffer()
stephbu
A: 

I guess it depends on what you are going to do with the data?

If you don't need it all at once you could just perform the read operation inside a loop?

janzi
+2  A: 

Putting it all together, assuming you're not getting a HUGE (more than can fit into memory)amount of data:

TcpClient tcpclnt = new TcpClient();
tcpclnt.Connect(ip, port);
Stream stm = tcpclnt.GetStream();
stm.Write(cmdBuffer, 0, cmdBuffer.Length);
MemoryStream ms = new MemoryStream();
byte[] buffer = new Byte[2048];
int length;
while ((length = stm.Read(buffer, 0, buffer.Length)) > 0)
    ms.Write(buffer, 0, length);
tcpclnt.Close();
byte[] response = ms.ToArray();

As mentioned the MemoryStream will handle the dynamic byte array allocation for you. And Stream.Read(byte[], int, int) will return the length of the bytes found in this 'read' or 0 if it's reached the end.

Clinton
thanks!! before I read responses I had something like this with array resizing, buffer copying.. only a couple more lines, but this is so much better
flamey
+1  A: 

Have you tried the StreamReader class? I'm not sure if it's applicable to this case, but I've used the StreamReader for reading HttpWebResponse response streams in the past. Very easy to use.

StreamReader reader = new StreamReader(stm);
String result = reader.ReadToEnd();
Jay S