我得到了一个文件流,其中包含从磁盘读取的内容。
Stream input = new FileStream("filename");
此流将被传递到第三方库,该库在读取流后,将流的位置指针保留在文件末尾(作为使用)。
我的要求不是每次都从桌面加载文件,而是要维护每次都会使用的MemoryStream
。
public static void CopyStream(Stream input, Stream output)
{
byte[] buffer = new byte[32768];
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, read);
}
}
我已经尝试了上面的代码。将输入流复制到输出流是第一次工作,但对CopyStream
的后续调用将不起作用,因为源的Position
将在第一次调用后位于流的末尾。
是否有其他替代方法可以将源流的内容复制到另一个流,而不管源流的当前Position
如何?
并且此代码需要在多线程环境中以线程安全的方式运行。
您可以使用 .NET 4.0 Stream.CopyTo 将 Steam 复制到 MemoryStream。内存流有一个 Position 属性,可用于将其位置移动到开头。
var ms = new MemoryStream();
using (Stream file = File.OpenRead(@"filename"))
{
file.CopyTo(ms);
}
ms.Position = 0;
要使线程安全解决方案,您可以将内容复制到字节数组,并为需要访问的每个线程创建一个新的 MemoryStream 包装字节数组:
byte[] fileBytes = ms.ToArray();
var ms2 = new MemoryStream(fileBytes);
您应该检查输入流的 CanSeek
属性。如果返回 false,则无论如何您只能读取一次。如果CanSeek
返回 true,则可以将位置设置为零并复制掉。
if (input.CanSeek)
{
input.Position = 0;
}
您可能还希望存储旧位置并在复制后恢复它。
ETA:传递相同的Stream
实例并不是最安全的做法。 例如,当您取回Stream
时,您无法确定它没有被处理掉。我建议一开始就将FileStream
复制到MemoryStream
,但只通过调用ToArray()
来存储后者的字节内容。当您需要在某处传递Stream
时,只需每次使用 new MemoryStream(byte[])
创建一个新即可。