从基本流中读取(httpRequestStream)

时间:2012-01-15 13:48:06

标签: c# .net http stream

我有一个基本流,它是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

3 个答案:

答案 0 :(得分:6)

您的错误位于以下行:

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);

答案 1 :(得分:5)

StreamReader也无法获得长度 - 似乎对Stream.Read的第三个参数存在一些混淆。该参数指定将要读取的最大字节数,它不需要(实际上不能)等于流中实际可用的字节数。您只需在循环中调用Read,直到它返回0,在这种情况下,您知道已到达流的末尾。这一切都记录在MSDN上,而且StreamReader也是如此。

使用StreamReader阅读请求并将其转入string也没有问题;字符串在.NET中是二进制安全的,所以你被覆盖了。问题在于理解字符串的内容,但由于您没有提供任何相关信息,我们无法真正谈论它。

答案 2 :(得分:0)

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;
    }