传递流的子序列而不将其内容复制到新实例中
Passing subsequence of a stream without copying its content into a new instance
假设我有以下方法:
void Upload(Stream stream)
{
// uploads the content of the specified stream somewhere
}
让我们进一步假设我得到了一些二进制文件 f
,其中包含一些我想使用上述方法上传的数据。
但是:我要上传的不是整个文件。只是f
的一部分。更准确地说,所需数据从某个位置 s >= 0
开始并在某个位置 e <= f.Length
结束。
有没有办法传递一个 Stream
实例,它从位置 s
开始,长度为 e
,而不复制 s
和 s
之间的所有字节e
到一个新的流实例?我问是因为有可能文件 f
很大,我不想对可能可用的 RAM 做出假设。
请考虑使用 Stream.CanSeek Property, Stream.Position Property, Stream.Seek Method 到 "access" 流的特定部分。
要有一个单独的 Stream
具有适当长度的实例,似乎需要实现一个 SubStream
class — 代表子流的包装器。以下参考资料可用于实现此类包装器:
- How to access part of a FileStream or MemoryStream, Social MSDN.
- How to expose a sub section of my stream to a user, Whosebug.
如果在调用该方法之前修改原始流中的指针可行,则使用Seek to set the starting position and SetLength设置结束位置。然后,您可以将流传递给该方法,它应该只触及该部分(假设它没有在内部寻求回到开头)。
不幸的是,SetLength
会截断流,因此如果出于某种原因需要,您以后将无法访问其余部分。但是,如果这不是必需的,这应该可行。
编辑:由于您需要保留原始流,这些是我能想到的其他选项:
- 如果您有权访问该路径(并且它未被其他流锁定),您可以打开一个新的文件流并发送该流的截断版本。
您可以将需要的部分复制到新的流中,例如 MemoryStream
。您不需要复制整个文件,但需要使用 Seek and Read.
复制要上传的部分
byte[] data = new byte[size];
stream.Seek(position, SeekOrigin.Begin);
stream.Read(data, 0, size);
using (MemoryStream subStream = new MemoryStream(data))
{
Upload(subStream);
}
您可以编写自己的流实现来执行您想要的操作,仅访问另一个流的特定部分。
假设我有以下方法:
void Upload(Stream stream)
{
// uploads the content of the specified stream somewhere
}
让我们进一步假设我得到了一些二进制文件 f
,其中包含一些我想使用上述方法上传的数据。
但是:我要上传的不是整个文件。只是f
的一部分。更准确地说,所需数据从某个位置 s >= 0
开始并在某个位置 e <= f.Length
结束。
有没有办法传递一个 Stream
实例,它从位置 s
开始,长度为 e
,而不复制 s
和 s
之间的所有字节e
到一个新的流实例?我问是因为有可能文件 f
很大,我不想对可能可用的 RAM 做出假设。
请考虑使用 Stream.CanSeek Property, Stream.Position Property, Stream.Seek Method 到 "access" 流的特定部分。
要有一个单独的 Stream
具有适当长度的实例,似乎需要实现一个 SubStream
class — 代表子流的包装器。以下参考资料可用于实现此类包装器:
- How to access part of a FileStream or MemoryStream, Social MSDN.
- How to expose a sub section of my stream to a user, Whosebug.
如果在调用该方法之前修改原始流中的指针可行,则使用Seek to set the starting position and SetLength设置结束位置。然后,您可以将流传递给该方法,它应该只触及该部分(假设它没有在内部寻求回到开头)。
不幸的是,SetLength
会截断流,因此如果出于某种原因需要,您以后将无法访问其余部分。但是,如果这不是必需的,这应该可行。
编辑:由于您需要保留原始流,这些是我能想到的其他选项:
- 如果您有权访问该路径(并且它未被其他流锁定),您可以打开一个新的文件流并发送该流的截断版本。
您可以将需要的部分复制到新的流中,例如
复制要上传的部分MemoryStream
。您不需要复制整个文件,但需要使用 Seek and Read.byte[] data = new byte[size]; stream.Seek(position, SeekOrigin.Begin); stream.Read(data, 0, size); using (MemoryStream subStream = new MemoryStream(data)) { Upload(subStream); }
您可以编写自己的流实现来执行您想要的操作,仅访问另一个流的特定部分。