C# 如何从开始复制流,而不考虑其当前位置

C# 如何从开始复制流,而不考虑其当前位置,c#,.net,stream,C#,.net,Stream,我得到了一个从磁盘读取内容的文件流 Stream input = new FileStream("filename"); 此流将被传递给第三方库,该库在读取流后,将流的位置指针保持在文件的末尾(通常情况下) 我的要求不是每次都从桌面加载文件,而是维护MemoryStream,每次都会使用它 public static void CopyStream(Stream input, Stream output) { byte[] buffer = new by

我得到了一个从磁盘读取内容的文件流

    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
的后续调用将不起作用,因为源的
位置将在第一次调用后位于流的末尾

是否有其他替代方案将源流的内容复制到另一个流,而不考虑源流的当前
位置


并且此代码需要在多线程环境中以线程安全的方式运行。

您应该检查输入流的
CanSeek
属性。如果返回false,则无论如何只能读取一次。如果
CanSeek
返回true,则可以将位置设置为零并复制

if (input.CanSeek)
{
    input.Position = 0;
}
您可能还希望存储旧位置,并在复制后将其还原


ETA:传递相同的
流实例
不是最安全的做法。例如,您无法确定
流在取回时是否未被处理。我建议在开始时将
文件流
复制到
内存流
,但只通过调用
ToArray()
存储后者的字节内容。当您需要将
传递到某个地方时,每次只需使用
新内存流(字节[])
创建一个新的流,您应该检查输入流的
CanSeek
属性。如果返回false,则无论如何只能读取一次。如果
CanSeek
返回true,则可以将位置设置为零并复制

if (input.CanSeek)
{
    input.Position = 0;
}
您可能还希望存储旧位置,并在复制后将其还原

ETA:传递相同的
流实例
不是最安全的做法。例如,您无法确定
流在取回时是否未被处理。我建议在开始时将
文件流
复制到
内存流
,但只通过调用
ToArray()
存储后者的字节内容。当您需要将
传递到某个地方时,每次只需使用
新内存流(字节[])

创建一个新的流即可。您可以使用.NET 4.0将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);
您可以使用.NET4.0将steam复制到MemoryStream。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);

如果流是可查找的,您只需将位置更改为零(
input.position=0;
)。或者,因为您将整个文件都保存在内存中,所以根本不要使用流:)同意。尽管从维护的角度来看,这里存在危险。如您所述,第三方库移动位置是因为它读取文件。它将来还能做什么?你在这里设置了一个不必要的维护头痛。您创建的缓冲区是32K,因此我们在处理时间和存储方面谈论的是微不足道的。那么为什么不每次都通过一条新的流呢?如果您按照@Luaan的建议将数据保存在内存中,则将副本传递给库以防止数据更改。经验法则,如果将可变数据提供给第三方库,永远不要依赖于可重用的数据。@JamesLucas“您创建的缓冲区是32K,因此我们在处理时间和存储方面谈论的是微不足道的。”这是一个临时缓冲区,对于成批复制,文件大小可能会更大/更小。如果流是可查找的,您只需将位置更改为零(
input.position=0;
)。或者,因为您将整个文件都保存在内存中,所以根本不要使用流:)同意。尽管从维护的角度来看,这里存在危险。如您所述,第三方库移动位置是因为它读取文件。它将来还能做什么?你在这里设置了一个不必要的维护头痛。您创建的缓冲区是32K,因此我们在处理时间和存储方面谈论的是微不足道的。那么为什么不每次都通过一条新的流呢?如果您按照@Luaan的建议将数据保存在内存中,则将副本传递给库以防止数据更改。根据经验,如果将可变数据提供给第三方库,永远不要依赖于可重用的数据。@JamesLucas“您创建的缓冲区是32K,所以我们在处理时间和存储方面谈论的是微不足道的。”这是一个临时缓冲区,对于成批复制,文件大小可以是更多/更少。