如何从开头复制流,无论其当前位置如何

时间:2015-04-28 07:41:22

标签: c# .net stream

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

foreach(DB::table('users')->paginate(2) as $object) {
   echo $object->name;
}

此流将被传递到第三方库,该第三方库在读取流之后将Stream的位置指针保持在文件的末尾(作为用途)。

我的要求是不是每次都从桌面加载文件,而是我想保留A1,B1,A2,B2,每次都会使用它。

object objCellText = Cells.GetType().InvokeMember("Item", 
                        BindingFlags.GetProperty,null,Cells, 
                        new object[] { RowIndex, ColIndex });

var CellText = objCellText.GetType().InvokeMember("Value",
                        BindingFlags.GetProperty, null, objCellText, null);

var CellName = objCellText.GetType().InvokeMember("Name",
                        BindingFlags.GetProperty, null, objCellText, null);

我试过上面的代码。它首次将输入流复制到输出流,但随后对Name的调用将无法正常工作,因为源 Stream input = new FileStream("filename"); 将位于流后的流的末尾。第一次打电话。

是否存在将源流的内容复制到另一个流的其他替代方案,而不管源流的当前MemoryStream

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

2 个答案:

答案 0 :(得分:3)

您可以使用.NET 4.0 Stream.CopyTo将您的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);

答案 1 :(得分:2)

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

if (input.CanSeek)
{
    input.Position = 0;
}

您可能还想存储旧位置并在复制后将其恢复。

ETA:传递Stream周围的相同实例并不是最安全的事情。例如。当你找回Stream时,你无法确定FileStream是否被处理掉了。我建议在开头将MemoryStream复制到ToArray(),但只能通过调用Stream来存储后者的字节内容。当您需要在某处传递new MemoryStream(byte[])时,只需使用ID Department Category 555 16 test 888 16 test 0001 16 test 创建一个新的。{/ p>