如何读取流并将其位置重置为零,即使是流.CanSeek==false

本文关键字:即使是 false CanSeek 何读取 读取 位置 | 更新日期: 2023-09-27 18:20:57

即使stream.CanSeek == false,我如何读取流并将其位置重置为零?我需要一些变通办法。

如何读取流并将其位置重置为零,即使是流.CanSeek==false

如果您的场景允许您替换原始流,那么您可以检查它是否支持搜索,如果不支持,则读取其内容并将其封装到新的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字符串中读取,因此不会浪费内存来创建数据的冗余副本。

使用另一个支持查找的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;
}

当然,如果您的流读取的数据不变,您可以简单地处理旧流,并创建一个读取相同数据的新流。