有谁知道我在哪里可以找到Stream splitter实现?
我正在寻找一个Stream,并获得两个独立的流,可以独立读取和关闭,而不会相互影响。这些流应该返回与原始流相同的二进制数据。无需实现职位或寻求等......仅向前。
我更喜欢它不只是将整个流复制到内存中并多次提供服务,这对于实现自己来说相当简单。
那里有什么可以做到的吗?
答案 0 :(得分:4)
没有开箱即用。
您需要以FIFO方式缓冲原始流中的数据,仅丢弃所有“读取器”流已读取的数据。
我会用:
答案 1 :(得分:3)
这可能会很棘手,而且不会将所有内容缓冲在内存中(如果流分别位于BOF和EOF)。
我想知道将流写入磁盘,复制并从磁盘读取两个流是不容易的,Close()
内置自我删除(即编写自己的Stream
围绕FileStream
)包装。
答案 2 :(得分:2)
如果不重复至少部分资源流,你不可能真正做到这一点 - 主要是因为如果听起来不像你可以控制它们消耗的速度(多线程?)。你可以做一些聪明的事情,一个人阅读另一个人的读取(从而只在那个点上制作副本),但这种复杂的听起来似乎不值得麻烦。
答案 3 :(得分:2)
以下似乎有效,称为EchoStream http://www.codeproject.com/Articles/3922/EchoStream-An-Echo-Tee-Stream-for-NET 它是一个非常古老的实现(2003),但应提供一些上下文
找到答案 4 :(得分:1)
我认为您无法找到通用实现来做到这一点。 Stream是相当抽象的,您不知道字节的来源。例如,你不知道它是否会支持寻求;而且你不知道操作的相对成本。 (Stream可能是从远程服务器读取数据的抽象,甚至是备份磁带的抽象!)。
如果您能够拥有MemoryStream并存储一次内容,则可以使用相同的缓冲区创建两个单独的流;它们将表现为独立的Streams但只使用一次内存。
否则,我认为你最好通过创建一个包装类来存储从一个流读取的字节,直到它们也被第二个流读取。这将为您提供所需的仅向前行为 - 但在最坏的情况下,如果在第一个Stream完成读取所有内容之前未读取第二个流,则可能存在将所有字节存储在内存中的风险。
答案 5 :(得分:1)
我已经在github和NuGet上提供了一个SplitStream。
就是这样。
using (var inputSplitStream = new ReadableSplitStream(inputSourceStream))
using (var inputFileStream = inputSplitStream.GetForwardReadOnlyStream())
using (var outputFileStream = File.OpenWrite("MyFileOnAnyFilestore.bin"))
using (var inputSha1Stream = inputSplitStream.GetForwardReadOnlyStream())
using (var outputSha1Stream = SHA1.Create())
{
inputSplitStream.StartReadAhead();
Parallel.Invoke(
() => {
var bytes = outputSha1Stream.ComputeHash(inputSha1Stream);
var checksumSha1 = string.Join("", bytes.Select(x => x.ToString("x")));
},
() => {
inputFileStream.CopyTo(outputFileStream);
},
);
}
我没有在非常大的流上测试它,但试一试。
答案 6 :(得分:-1)
随着async / await的引入,只要你的一个读取任务都是异步的,你应该能够只使用一个OS线程处理相同的数据两次。
我认为你想要的是你到目前为止看到的数据块的链接列表。然后,您可以拥有多个自定义Stream实例,其中包含指向此列表的指针。当块从列表的末尾掉落时,它们将被垃圾收集。立即重用内存需要一些其他类型的循环列表和引用计数。可行,但更复杂。
当您的自定义Stream可以从缓存中应答ReadAsync调用时,复制数据,将指针向下推进列表并返回。
当您的Stream已赶上缓存列表的末尾时,您希望在不等待它的情况下向基础流发出单个ReadAsync,并使用数据块缓存返回的Task。因此,如果任何其他Stream阅读器也会在此读取完成之前赶上并尝试阅读更多内容,则可以返回相同的Task对象。
这样,两个读者都会将等待继续挂钩到同一ReadAsync调用的结果。当单个读取返回时,两个读取任务将按顺序执行其过程的下一步。