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がtrueであるかどうかを確認できます。多くのストリームは、ストリーミングされているため、長さを事前に知ることができない性質のものです。

長さを知る必要がある場合は、ストリーム全体を実際にバッファリングして、事前にメモリにロードする必要があります。

于 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

常にストリームの長さを取得できるとは限りません。たとえば、ネットワーク ストリームの場合、長さを確認する唯一の方法は、ストリームが閉じられるまでデータを読み取ることです。

あなたは何をしようとしているのですか?ストリームが使い果たされるまで読み込んで、データを にコピーMemoryStreamできますか?

于 2010-07-30T16:45:19.893 に答える
6

シークをサポートしていない場合、ストリームの長さを取得できるとは限りません。Streamクラスの例外テーブルを参照してください。

たとえば、別のプロセス(ネットワークストリーム、標準出力など)に接続されたストリームは、他のプロセスの記述方法に応じて任意の量の出力を生成でき、フレームワークがデータの量を把握する方法はありません。 。

一般的なケースでは、ストリームの最後まですべてのデータを読み込んでから、読み取った量を把握する必要があります。

于 2010-07-30T16:47:02.353 に答える
0

TcpClient.EndRead()は、ストリーム内のバイト数を返す必要があります。

-編集、もちろん、TCPストリームを使用する必要があります

于 2010-07-30T16:49:57.573 に答える