Stream.Length создает исключение NotSupportedException - PullRequest
27 голосов
/ 30 июля 2010

Я получаю сообщение об ошибке при попытке выполнения stream.Length для объекта Stream, отправленного в мой метод WCF.

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

Как вы получаете длину потока? какие-нибудь примеры?

Ответы [ 6 ]

30 голосов
/ 30 июля 2010

Stream.Length работает только в реализациях Stream, где доступен поиск.Обычно вы можете проверить, является ли Stream.CanSeek истинным.Многие потоки, так как они потоковые , имеют природу, в которой невозможно заранее узнать длину.

Если вы должны знать длину, вам, возможно, придется фактически буферизоватьвесь поток, заранее загружая его в память.

10 голосов
/ 21 октября 2012

Я столкнулся с той же проблемой при использовании служб 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. 
    }
7 голосов
/ 08 января 2014

Вот что я делаю:

    // 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;
    }
6 голосов
/ 30 июля 2010

Не всегда возможно получить длину потока, если он не поддерживает поиск.См. Таблицу исключений в Потоковый класс .

Например, поток, подключенный к другому процессу (сетевой поток, стандартный вывод и т. Д.), Может произвести любое количество вывода, в зависимости от того, какдругой процесс написан, и у фреймворка нет возможности выяснить, сколько там данных.

В общем случае вам просто нужно прочитать все данные до конца потока изатем выясните, сколько вы прочитали.

6 голосов
/ 30 июля 2010

Вы не всегда можете получить длину потока. В случае сетевого потока единственный способ узнать длину - это прочитать данные из него, например, до его закрытия.

Что ты пытаешься сделать? Не могли бы вы читать из потока, пока он не исчерпан, копируя данные в MemoryStream по ходу?

0 голосов
/ 30 июля 2010

TcpClient.EndRead () должен возвращать количество байтов в потоке.

- Изменить, конечно, вам нужно использовать TCP-поток

...