如何读取流并将其位置重置为零,即使是流.CanSeek==false
本文关键字:即使是 false CanSeek 何读取 读取 位置 | 更新日期: 2023-09-27 18:20:57
即使stream.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;
}
当然,如果您的流读取的数据不变,您可以简单地处理旧流,并创建一个读取相同数据的新流。