传递流的子序列而不将其内容复制到新实例

时间:2015-05-27 22:59:57

标签: c# stream filestream

我们假设我有以下方法:

void Upload(Stream stream)
{
    // uploads the content of the specified stream somewhere
}

让我们进一步假设我得到了一些二进制文件f,其中包含一些我想用上述方法上传的数据。 但是:它不是我要上传的整个文件。它只是f的某个部分。更准确地说,所需数据从某个位置s >= 0开始,到达某个位置e <= f.Length

有没有办法传递Stream实例,该实例从位置s开始,长度为e,而不会复制s和{{之间的所有字节1}}进入新的流实例?我问,因为有可能,文件e非常大,我不想对潜在的可用内存进行假设。

2 个答案:

答案 0 :(得分:2)

请考虑使用Stream.CanSeek PropertyStream.Position PropertyStream.Seek Method来“访问”流的特定部分。

要拥有一个具有适当长度的单独Stream实例,似乎需要实现一个SubStream类 - 表示子流的包装器。以下引用对于实现这样的包装器非常有用:

  1. How to access part of a FileStream or MemoryStream, Social MSDN
  2. How to expose a sub section of my stream to a user, Stackoverflow

答案 1 :(得分:1)

如果在调用方法之前修改原始流中的指针,则使用Seek设置起始位置,使用SetLength设置结束位置。然后,您可以将流传递给方法,它应该只触摸该部分(假设它不在内部寻找回到开头)。

不幸的是,SetLength会截断流,因此如果您出于某种原因需要,您将无法再访问其余部分。但是,如果这不是一项要求,那么这应该有效。

编辑:由于您需要保留原始流,这些是我能想到的其他选项:

  • 如果您有权访问该路径(并且未被其他流锁定),则可以打开该文件的新流并发送该流的截断版本。
  • 您可以将所需的部分复制到新的流中,例如MemoryStream。您不需要复制整个文件,但您需要使用SeekRead复制要上传的部分。

    byte[] data = new byte[size];
    stream.Seek(position, SeekOrigin.Begin);
    stream.Read(data, 0, size);
    using (MemoryStream subStream = new MemoryStream(data))
    {
        Upload(subStream);
    }
    
  • 您可以编写自己的流实现来执行您想要的操作,只访问另一个流的特定部分。