C# 如何读取流并将其位置重置为零,即使Stream.CanSeek==false
如何读取流并将其位置重置为零,即使C# 如何读取流并将其位置重置为零,即使Stream.CanSeek==false,c#,.net,C#,.net,如何读取流并将其位置重置为零,即使Stream.CanSeek==false?我需要一些解决方法。使用另一个支持查找的流实现。如果Stream.CanSeek返回false,则该实现声明它不支持查找 MemoryStream对象不支持查找。您可以使用类似的方法将任意流复制到MemoryStream,生成的流将支持查找,例如,您可以将位置重置为0并重复读取 MemoryStream CopyStreamToMemory(Stream inputStream) { MemoryStream
Stream.CanSeek==false
?我需要一些解决方法。使用另一个支持查找的流实现。如果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;
}
当然,如果您的流读取的数据没有变化,您可以简单地处理旧流,并创建一个读取相同数据的新流。如果您的场景允许您替换原始流,那么您可以检查它是否支持查找,如果不支持,则读取其内容并将其包装到新的
内存流中,然后可以用于后续操作
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
只读取您的内容
字符串,因此您不会浪费内存创建数据的冗余副本。如果CanSeek==false
,任何此类尝试都可能导致异常。@oded;我知道,;这就是为什么我会问这样一个问题:在你有非常大的数据之前,这种方法是正确的。如果您有一些千兆字节,那么最好重新初始化您的流。在我看来,流式处理的目的不是存储您正在处理的所有数据。您关于MemoryStream
不适合大数据的说法是正确的。存储还是重新初始化流取决于场景。例如,如果您正在处理从Internet下载的数据,并且需要多次读取,则最好将数据存储在本地(内存或临时文件中),而不是再次下载。