35

在发送到我的 WCF 方法的 Stream 对象上尝试 stream.Length 时出现错误。

Unhandled Exception!
 Error ID: 0
 Error Code: Unknown
 Is Warning: False
 Type: System.NotSupportedException
 Stack:    at System.ServiceModel.Dispatcher.StreamFormatter.MessageBodyStream.get_Length()

你如何获得流的长度?有什么例子吗?

4

6 回答 6

35

Stream.Length仅适用于可查找的 Stream 实现。您通常可以检查Stream.CanSeek是否为真。许多流,因为它们正在被流式传输,具有无法提前知道长度的性质。

如果您必须知道长度,您可能需要实际缓冲整个流,提前将其加载到内存中。

于 2010-07-30T16:46:34.400 回答
13

这就是我所做的:

// Return the length of a stream that does not have a usable Length property
public static long GetStreamLength(Stream stream)
{
    long originalPosition = 0;
    long totalBytesRead = 0;

    if (stream.CanSeek)
    {
        originalPosition = stream.Position;
        stream.Position = 0;
    }

    try
    {
        byte[] readBuffer = new byte[4096];
        int bytesRead;

        while ((bytesRead = stream.Read(readBuffer, 0, 4096)) > 0)
        {
            totalBytesRead += bytesRead;
        }

    }
    finally
    {
        if (stream.CanSeek)
        {
            stream.Position = originalPosition;
        }
    }

    return totalBytesRead;
}
于 2014-01-08T08:41:12.927 回答
12

我在使用 WCF 服务时遇到了同样的问题。我需要获取 POST 消息的内容,并且Stream在我的方法中使用了一个参数来获取消息正文的内容。一旦我得到流,我想一次读取它的内容,并且需要知道我需要什么大小的字节数组。因此,在分配数组时,我会调用System.IO.Stream.Length并获取 OP 提到的异常。您需要知道流的长度以便可以读取整个流的内容的原因是什么?

您实际上可以使用System.IO.StreamReader. 如果您仍然需要知道流的大小,可以获取结果字符串的长度。这是我如何解决此问题的代码:

    [OperationContract]
    [WebInvoke(UriTemplate = "authorization")]
    public Stream authorization(Stream body)
    {
        // Obtain the token from the body
        StreamReader bodyReader = new StreamReader(body);
        string bodyString = bodyReader.ReadToEnd();
        int length = bodyString.Length; // (If you still need this.)
       // Do whatever you want to do with the body contents here. 
    }
于 2012-10-21T00:05:45.963 回答
7

你不能总是得到流的长度。例如,在网络流的情况下,找出长度的唯一方法是从中读取数据,直到它关闭。

你想做什么?您可以从流中读取直到用尽,然后将数据复制到 aMemoryStream中吗?

于 2010-07-30T16:45:19.893 回答
6

如果不支持查找,则并不总是可以获得流的长度。请参阅Stream 类的异常表。

例如,连接到另一个进程(网络流、标准输出等)的流可以产生任意数量的输出,具体取决于另一个进程的编写方式,并且框架无法确定有多少数据.

在一般情况下,您只需读取所有数据直到流结束,然后计算出您已读取了多少。

于 2010-07-30T16:47:02.353 回答
0

TcpClient.EndRead() 应该返回流中的字节数。

--编辑,当然你需要使用 TCP 流

于 2010-07-30T16:49:57.573 回答