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,所以我们在处理时间和存储方面谈论的是微不足道的。”这是一个临时缓冲区,对于成批复制,文件大小可以是更多/更少。