首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何将两个System.Io.Stream实例连接成一个实例?

如何将两个System.Io.Stream实例连接成一个实例?
EN

Stack Overflow用户
提问于 2010-10-07 14:19:22
回答 4查看 14.6K关注 0票数 31

假设我想要将三个文件一起流式传输给一个用户,但是他没有给我一个Stream对象来下推字节,而是我必须给他一个Stream对象,让他从中提取字节。我想获取我的三个FileStream对象(或者更聪明的是一个IEnumerable<Stream>),并返回一个新的ConcatenatedStream对象,该对象将按需从源流中拉出。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-10-07 14:33:29

class ConcatenatedStream : Stream
{
    Queue<Stream> streams;

    public ConcatenatedStream(IEnumerable<Stream> streams)
    {
        this.streams = new Queue<Stream>(streams);
    }

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

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

        while (count > 0 && streams.Count > 0)
        {
            int bytesRead = streams.Peek().Read(buffer, offset, count);
            if (bytesRead == 0)
            {
                streams.Dequeue().Dispose();
                continue;
            }

            totalBytesRead += bytesRead;
            offset += bytesRead;
            count -= bytesRead;
        }

        return totalBytesRead;
    }

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

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

    public override void Flush()
    {
        throw new NotImplementedException();
    }

    public override long Length
    {
        get { throw new NotImplementedException(); }
    }

    public override long Position
    {
        get
        {
            throw new NotImplementedException();
        }
        set
        {
            throw new NotImplementedException();
        }
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        throw new NotImplementedException();
    }

    public override void SetLength(long value)
    {
        throw new NotImplementedException();
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        throw new NotImplementedException();
    }
}
票数 33
EN

Stack Overflow用户

发布于 2010-10-07 14:36:07

未经测试,但类似于:

class StreamEnumerator : Stream
{
    private long position;
    bool closeStreams;
    IEnumerator<Stream> iterator;
    Stream current;
    private void EndOfStream() {
        if (closeStreams && current != null)
        {
            current.Close();
            current.Dispose();
        }
        current = null;
    }
    private Stream Current
    {
        get {
            if(current != null) return current;
            if (iterator == null) throw new ObjectDisposedException(GetType().Name);
            if (iterator.MoveNext()) {
                current = iterator.Current;
            }
            return current;
        }
    }
    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            EndOfStream();
            iterator.Dispose();
            iterator = null;
            current = null;
        }
        base.Dispose(disposing);
    }
    public StreamEnumerator(IEnumerable<Stream> source, bool closeStreams)
    {
        if (source == null) throw new ArgumentNullException("source");
        iterator = source.GetEnumerator();
        this.closeStreams = closeStreams;
    }
    public override bool CanRead { get { return true; } }
    public override bool CanWrite { get { return false; } }
    public override void Write(byte[] buffer, int offset, int count)
    {
        throw new NotSupportedException();
    }
    public override void WriteByte(byte value)
    {
        throw new NotSupportedException();
    }
    public override bool CanSeek { get { return false; } }
    public override bool CanTimeout { get { return false; } }
    public override void SetLength(long value)
    {
        throw new NotSupportedException();
    }
    public override long Seek(long offset, SeekOrigin origin)
    {
        throw new NotSupportedException();
    }
    public override void Flush()
    { /* nothing to do */ }
    public override long Length
    {
        get { throw new NotSupportedException(); }
    }
    public override long Position
    {
        get { return position; }
        set { if (value != this.position) throw new NotSupportedException(); }
    }
    public override int Read(byte[] buffer, int offset, int count)
    {
        int result = 0;
        while (count > 0)
        {
            Stream stream = Current;
            if (stream == null) break;
            int thisCount = stream.Read(buffer, offset, count);
            result += thisCount;
            count -= thisCount;
            offset += thisCount;
            if (thisCount == 0) EndOfStream();
        }
        position += result;
        return result;
    }
}
票数 9
EN

Stack Overflow用户

发布于 2017-11-16 04:28:05

这里有一个支持搜索的选项,这在许多情况下都是必要的。它缺少一些处理底层流的功能,如果您愿意假设底层流不会改变长度,那么它可能会更高效一些。然后可以一次计算总长度和流偏移量。

public sealed class ConcatenatedStream : Stream
{
    List<Stream> streams;
    private long _Position { get; set; }

    public ConcatenatedStream(List<Stream> streams)
    {
        this.streams = streams;
        Seek(0, SeekOrigin.Begin);
    }

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

    public override int Read(byte[] buffer, int offset, int count)
    {
        if (streams.Count == 0)
            return 0;

        var startStream = 0;
        var cumulativeCapacity = 0L;
        for (var i = 0; i < streams.Count; i++)
        {
            cumulativeCapacity += streams[i].Length;
            if (_Position < cumulativeCapacity)
            {
                startStream = i;
                break;
            }
        }

        var bytesRead = 0;
        var curStream = startStream;

        while (_Position < Length && bytesRead < count && curStream < streams.Count)
        {
            var r = streams[curStream].Read(buffer, offset + bytesRead, count - bytesRead);
            bytesRead += r;
            Seek(_Position + r, SeekOrigin.Begin);
            curStream++;
        }

        return bytesRead;
    }

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

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

    public override void Flush()
    {
        throw new NotImplementedException();
    }

    public override long Length
    {
        get {
            long length = 0;
            for (var i = 0; i < streams.Count; i++)
            {
                length += streams[i].Length;
            }
            return length;
        }
    }

    public override long Position
    {
        get
        {
            return _Position;
        }
        set
        {
            Seek(value, SeekOrigin.Begin);
        }
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        if (origin == SeekOrigin.Begin)
        {
            _Position = offset;

            var prevLength = 0L;
            var cumulativeLength = 0L;
            for (var i = 0; i < streams.Count; i++)
            {
                cumulativeLength += streams[i].Length;
                if (offset < cumulativeLength)
                {
                    streams[i].Seek(offset - prevLength, SeekOrigin.Begin);
                    return _Position;
                }
                prevLength = cumulativeLength;
            }
        }

        if (origin == SeekOrigin.Current)
        {
            var newAbs = _Position + offset;
            return Seek(newAbs, SeekOrigin.Begin);
        } 
        else if(origin == SeekOrigin.End)
        {
            var newAbs = Length - offset;
            return Seek(newAbs, SeekOrigin.Begin);
        }

        throw new NotImplementedException();
    }

    public override void SetLength(long value)
    {
        throw new NotImplementedException();
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        throw new NotImplementedException();
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3879152

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档