web-dev-qa-db-ja.com

Stream.LengthがNotSupportedExceptionをスローする

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

ストリームの長さをどのように取得しますか?何か例は?

30
Nevin Mathai

Stream.Length は、シークが可能なStream実装でのみ機能します。通常、 Stream.CanSeek がtrueかどうかを確認できます。多くのストリームはstreamedであるため、事前に長さを知ることは不可能です。

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

31
Reed Copsey

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. 
    }
10
froggythefrog

これが私がすることです:

    // 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;
    }
8
Paul Bartlett

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

あなたは何をしようとしているのですか?ストリームがなくなるまでストリームから読み取り、データをMemoryStreamにコピーしますか?

6
Jon Skeet

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

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

一般的なケースでは、ストリームの終わりまですべてのデータを読み取って、どれだけ読み取ったかを把握する必要があります。

6
dsolimano

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

-編集、もちろん、TCP Streamを使用する必要があります

0
daiglebagel