Как прочитать поток и сбросить его позицию на ноль, даже если stream.CanSeek == false - PullRequest
7 голосов
/ 22 января 2012

Как мне прочитать поток и сбросить его положение на ноль, даже если stream.CanSeek == false?Мне нужно немного поработать.

Ответы [ 2 ]

10 голосов
/ 22 января 2012

Если ваш сценарий позволяет вам заменить исходный поток, то вы можете проверить, поддерживает ли он поиск, и, если нет, прочитать его содержимое и обернуть их в новый MemoryStream, который вы затем сможете использовать для последующих операций.

static string PeekStream(ref Stream stream)
{
    string content;
    var reader = new StreamReader(stream);
    content = reader.ReadToEnd();

    if (stream.CanSeek)
    {
        stream.Seek(0, SeekOrigin.Begin);
    }
    else
    {
        stream.Dispose();
        stream = new MemoryStream(Encoding.UTF8.GetBytes(content));
    }

    return content;
}

Вышеупомянутое довольно неэффективно, поскольку оно должно выделять память в два раза больше вашего контента.Я бы порекомендовал адаптировать части вашего кода, к которым вы обращаетесь к потоку (после прочтения всего его содержимого), чтобы они вместо этого могли получить доступ к сохраненной копии вашего содержимого.Например:

string content;
using (var reader = new StreamReader(stream))
    content = reader.ReadToEnd();

// Process content here.

string line;
using (var reader = new StringReader(content))
    while ((line = reader.ReadLine()) != null)
        Console.WriteLine(line);

Поскольку StringReader только читает из вашей строки content, вы не будете тратить память на создание избыточных копий ваших данных.

6 голосов
/ 22 января 2012

Используйте другую реализацию Stream, которая поддерживает поиск.Если Stream.CanSeek возвращает false, то эта реализация утверждает, что не поддерживает поиск.

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

MemoryStream CopyStreamToMemory(Stream inputStream)
{
    MemoryStream ret = new MemoryStream();
    const int BUFFER_SIZE = 1024;
    byte[] buf = new byte[BUFFER_SIZE];

    int bytesread = 0;
    while ((bytesread = inputStream.Read(buf, 0, BUFFER_SIZE)) > 0)
        ret.Write(buf, 0, bytesread);

    ret.Position = 0;
    return ret;
}

Конечно, есливаш поток читает данные, которые не меняются, вы можете просто удалить старый поток и создать новый поток, который читает те же данные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...