我有一个基本流,它是HTTP请求流和
var s=new HttpListener().GetContext().Request.InputStream;
我想读取流(其中包含非字符内容,因为我已经发送了数据包)
当我们用StreamReader包装这个流时,我们使用StreamReader的ReadToEnd()函数,它可以读取整个流并返回一个字符串。。。
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
但由于它包含非字符内容,我们不能使用StremReader(我尝试了所有的编码机制。使用字符串是错误的)。我不能使用函数
context.Request.InputStream.Read(buffer,position,Len)
因为我无法获得流的长度,InputStream.length总是抛出一个异常,无法使用。。我不想创建一个像[size][file]这样的小协议,先读取大小,然后再读取文件。。。StreamReader可以以某种方式获得长度。。我只想知道怎么做。我也试过这个,但它不起作用
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();
}
我通过下面的解决了这个问题
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();
感谢Jon,Douglas
您的错误位于以下行:
byte b = (byte)ss.ReadByte();
byte
类型是无符号的;当Stream.ReadByte
在流的末尾返回-1时,您不加区分地将其强制转换为byte
,后者将其转换为255,因此满足b >= 0
条件。值得注意的是,返回类型是int
,而不是byte
,正是因为这个原因。
一个快速而肮脏的修复你的代码:
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();
}
以下解决方案更有效,因为它避免了ReadByte
调用引起的逐字节读取,而是为Read
调用使用动态扩展的字节数组(类似于List<T>
的内部实现方式):
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);
StreamReader
也无法获得长度——似乎对Stream.Read
的第三个参数有一些混淆。该参数指定将读取的最大字节数,该字节数不需要(也不可能)等于流中实际可用的字节数。您只需在循环中调用Read
,直到它返回0
,在这种情况下,您就知道您已经到达了流的末尾。这一切都记录在MSDN上,StreamReader
也是这样做的
使用StreamReader
读取请求并将其放入string
也没有问题;字符串在.NET中是二进制安全的,所以您已经了解了。问题是理解字符串的内容,但我们不能真正讨论这个问题,因为您没有提供任何相关信息。
HttpRequestStream
不会给您长度,但您可以从HttpListenerRequest.ContentLength64
属性中获取长度。正如Jon所说,请确保观察Read
方法的返回值。在我的例子中,我们得到缓冲读取,不能一次读取整个226KB的有效负载。
尝试
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;
}