5

I have a basic stream which is the stream of HTTP request and

var s=new HttpListener().GetContext().Request.InputStream; 

I want to read the stream (which contain non-Character content, because i've sent the packet)

When we wrap this stream by StreamReader then we use the ReadToEnd() function of StreamReader it can read the whole stream and return a string...

HttpListener listener = new HttpListener(); listener.Prefixes.Add("http://127.0.0.1/"); listener.Start(); var context = listener.GetContext(); var sr = new StreamReader(context.Request.InputStream); string x=sr.ReadToEnd(); //This Workds 

but since it has nonCharacter content we cant use StremReader (i tried all encoding mechanisms..using string is just wrong).And i Cant use the function

context.Request.InputStream.Read(buffer,position,Len) 

because I cant get the length of the stream, InputStream.Length always throws an exception and cant be used..and i dont want to create a small protocol like [size][file] and read first size then the file ...somehow the StreamReader can get the length ..and i just want to know how . I also tried this and it didn't work

List<byte> bb = new List<byte>(); var ss = context.Request.InputStream; byte b = (byte)ss.ReadByte(); while (b >= 0) { bb.Add(b); b = (byte)ss.ReadByte(); } 

I've solved it by the following

FileStream fs = new FileStream("C:\\cygwin\\home\\Dff.rar", FileMode.Create); byte[] file = new byte[1024 * 1024]; int finishedBytes = ss.Read(file, 0, file.Length); while (finishedBytes > 0) { fs.Write(file, 0, finishedBytes); finishedBytes = ss.Read(file, 0, file.Length); } fs.Close(); 

thanks Jon , Douglas

1
  • I assume your last version should work. Two hints: (1) Learn to use the 'using' statement for automatically closing the FileStream. (2) You probably don't need such a massive byte[] buffer, since you're unlikely to read that much data in any single Read call. A size of around 8192 would probably be enough. Commented Jan 15, 2012 at 14:44

3 Answers 3

6

Your bug lies in the following line:

byte b = (byte)ss.ReadByte(); 

The byte type is unsigned; when Stream.ReadByte returns -1 at the end of the stream, you’re indiscriminately casting it to byte, which converts it to 255 and, therefore, satisfies the b >= 0 condition. It is helpful to note that the return type is int, not byte, for this very reason.

A quick-and-dirty fix for your code:

List<byte> bb = new List<byte>(); var ss = context.Request.InputStream; int next = ss.ReadByte(); while (next != -1) { bb.Add((byte)next); next = ss.ReadByte(); } 

The following solution is more efficient, since it avoids the byte-by-byte reads incurred by the ReadByte calls, and uses a dynamically-expanding byte array for Read calls instead (similar to the way that List<T> is internally implemented):

var ss = context.Request.InputStream; byte[] buffer = new byte[1024]; int totalCount = 0; while (true) { int currentCount = ss.Read(buffer, totalCount, buffer.Length - totalCount); if (currentCount == 0) break; totalCount += currentCount; if (totalCount == buffer.Length) Array.Resize(ref buffer, buffer.Length * 2); } Array.Resize(ref buffer, totalCount); 
Sign up to request clarification or add additional context in comments.

1 Comment

Lol, i just saw your comment..thanks for the info ...but I will use the file as the second array ..so I wont need resizing the array
5

StreamReader cannot get the length either -- it seems there's some confusion regarding the third parameter of Stream.Read. That parameter specifies the maximum number of bytes that will be read, which does not need (and really cannot) be equal to the number of bytes actually available in the stream. You just call Read in a loop until it returns 0, in which case you know you have reached the end of the stream. This is all documented on MSDN, and it's also exactly how StreamReader does it.

There's also no problem in reading the request with StreamReader and getting it into string; strings are binary safe in .NET, so you 're covered. The problem will be making sense of the contents of the string, but we can't really talk about that since you don't provide any relevant information.

4 Comments

True ..I didnt explain that much ..What I ment by the len is an already created byte[] b=new byte[len] but this len i cant get it ..and my problem with strings is that we must use encoding in both ways from bytes to string and vise versa..but in the encoding step always messes my bytes ..
And i triend var sr = new StreamReader(context.Request.InputStream, Encoding.ASCII); and unicode and UTF8 then used "New AsciiEncoding().GetBytes(str)" and i got scrumbled bytes ..
and the ReadByte function returns -1 at end of stream ..still got infinite loop..
@CnativeFreak: You can not and you also need not get the length. Pick your own buffer size and read repeatedly. Also, you cannot use any encoding other than ASCII because that will mess up your input data. But you still have not provided any info on what you are actually trying to do.
0

HttpRequestStream won't give you the length, but you can get it from the HttpListenerRequest.ContentLength64 property. Like Jon said, make sure you observe the return value from the Read method. In my case, we get buffered reads and cannot read our entire 226KB payload in one go.

Try

 byte[] getPayload(HttpListenerContext context) { int length = (int)context.Request.ContentLength64; byte[] payload = new byte[length]; int numRead = 0; while (numRead < length) numRead += context.Request.InputStream.Read(payload, numRead, length - numRead); return payload; } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.