C# 是否有一种内置方式将多个文件作为一个流处理?

C# 是否有一种内置方式将多个文件作为一个流处理?,c#,.net,C#,.net,我有一个文件列表,我需要按特定顺序将每个文件读入给定大小的字节[]。对于单个文件来说,这本身并不是一个问题,一个简单的while((get=fs.Read(piece,0,piecenegth))>0)可以很好地完成工作。文件的最后一部分可能比所需的小,这很好 现在,有一个棘手的问题:如果我有多个文件,我需要有一个连续的流,这意味着如果文件的最后一个片段小于这个片段长度,那么我需要读取下一个文件的片段长度,然后继续读到最后一个文件的结尾 因此,基本上,给定X个文件,我总是会读取长度正好是片段长度

我有一个文件列表,我需要按特定顺序将每个文件读入给定大小的字节[]。对于单个文件来说,这本身并不是一个问题,一个简单的while((get=fs.Read(piece,0,piecenegth))>0)可以很好地完成工作。文件的最后一部分可能比所需的小,这很好

现在,有一个棘手的问题:如果我有多个文件,我需要有一个连续的流,这意味着如果文件的最后一个片段小于这个片段长度,那么我需要读取下一个文件的片段长度,然后继续读到最后一个文件的结尾

因此,基本上,给定X个文件,我总是会读取长度正好是片段长度的片段,除了最后一个文件的最后一个片段,它可能更小

我只是想知道在.net(3.5SP1)中是否已经有一些内置的东西可以做到这一点。我目前的方法是创建一个类,该类接受一个文件列表,然后公开一个
Read(byte[]buffer,long index,long length)
函数,类似于FileStream.Read()。这应该是非常直截了当的,因为我不必更改读取数据的调用代码,但在我重新发明轮子之前,我只想再次检查轮子是否已经内置到BCL中


谢谢:)

我不相信框架中有任何东西,但我建议让它更灵活一点——在构造函数中使用
IEnumerable
,然后自己从
流中派生。然后,要获取文件流,您可以(假设C#3.0)只需执行以下操作:


这里的“所有权”部分有点棘手-上面的部分允许组合流拥有它从中读取的任何流的所有权,但您可能不希望它必须遍历所有其他流,如果它过早关闭,则关闭所有流。

以下是我根据@jon skeet的想法提出的

这对我来说已经足够了。(但我不需要关于实现BeginRead/EndRead方法的帮助。)下面是包含sync和async-Read以及BeginRead/EndRead的完整代码


这实际上是一个很好的方法,我只是不确定是否要实现自己的流。与IEnumerable不同,a也可以工作,因为这样我的CombinationStream就可以完全控制“内部流”。我会考虑哪种方法最适合我。
Stream combined = new CombinationStream(files.Select(file => File.Open(file));
internal class CombinationStream : System.IO.Stream
{
    private readonly System.Collections.Generic.IList<System.IO.Stream> _streams;
    private int _currentStreamIndex;
    private System.IO.Stream _currentStream;
    private long _length = -1;
    private long _postion;

    public CombinationStream(System.Collections.Generic.IList<System.IO.Stream> streams)
    {
        if (streams == null)
        {
            throw new System.ArgumentNullException("streams");
        }

        _streams = streams;
        if (streams.Count > 0)
        {
            _currentStream = streams[_currentStreamIndex++];
        }
    }

    public override void Flush()
    {
        if (_currentStream != null)
        {
            _currentStream.Flush();
        }
    }

    public override long Seek(long offset, System.IO.SeekOrigin origin)
    {
        throw new System.InvalidOperationException("Stream is not seekable.");
    }

    public override void SetLength(long value)
    {
        this._length = value;
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        int result = 0;
        int buffPostion = offset;

        while (count > 0)
        {
            int bytesRead = _currentStream.Read(buffer, buffPostion, count);
            result += bytesRead;
            buffPostion += bytesRead;
            _postion += bytesRead;

            if (bytesRead <= count)
            {
                count -= bytesRead;
            }

            if (count > 0)
            {
                if (_currentStreamIndex >= _streams.Count)
                {
                    break;
                }

                _currentStream = _streams[_currentStreamIndex++];
            }
        }

        return result;
    }

    public override long Length
    {
        get
        {
            if (_length == -1)
            {
                _length = 0;
                foreach (var stream in _streams)
                {
                    _length += stream.Length;
                }
            }

            return _length;
        }
    }

    public override long Position
    {
        get { return this._postion; }
        set { throw new System.NotImplementedException(); }
    }
    public override void Write(byte[] buffer, int offset, int count)
    {
        throw new System.InvalidOperationException("Stream is not writable");
    }

    public override bool CanRead
    {
        get { return true; }
    }

    public override bool CanSeek
    {
        get { return false; }
    }

    public override bool CanWrite
    {
        get { return false; }
    }
}
Install-Package CombinationStream