Is there a built-in way to handle multiple files as a single stream?

I have a list of files, and I need to read them each in a specific order in bytes [] of a given size. This in itself is not a problem for a single file, a simple while ((got = fs.Read (piece, 0, pieceLength))> 0) does the job perfectly. The last fragment of the file may be less than desired, which is excellent.

Now there is a difficult bit: if I have several files, I need to have one continuous stream, which means that if the last fragment of the file is less than lengthLength, then I need to read (itemLength-got) of the next file, and then continue to the end last file.

So essentially, with X files in mind, I will always read snippets that are exactly lengthLength long, except for the very last part of the very last file, which may be smaller.

I'm just wondering if there is anything in .net (3.5 SP1) that does the trick. My current approach is to create a class that takes a list of files and then provides a function Read(byte[] buffer, long index, long length)similar to FileStream.Read (). It should be pretty simple, because I don’t need to change the calling code that reads the data, but before I invent the wheel, I just wanted to check that the wheel is not already built into BCL.

Thanks:)

+5
source share
2 answers

, - IEnumerable<Stream> Stream . , , ( # 3.0) :

Stream combined = new CombinationStream(files.Select(file => File.Open(file));

"" - , , , , , , .

+6

@jon skeet.

Read, . ( BeginRead/EndRead.) , , - Read BeginRead/EndRead - https://github.com/prabirshrestha/CombinationStream/blob/master/src/CombinationStream-Net20/CombinationStream.cs https://github.com/facebook-csharp-sdk/CombinationStream/blob/master/src/CombinationStream-Net20/CombinationStream.cs

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; }
    }
}

NuGet

Install-Package CombinationStream
+3

All Articles