C# 如何向用户公开我的流的一个子部分

C# 如何向用户公开我的流的一个子部分,c#,stream,filestream,C#,Stream,Filestream,我有一个包含许多数据片段的流。我只想在另一个流中公开该数据的一部分。我要提取的数据块通常可以超过100mb。因为我已经有了包含数据的流,所以将该数据复制到另一个流并返回该数据似乎是一种浪费。我要寻找的是一种在控制第二个流可以引用多少数据的同时引用第一个流中的数据的方法。这是否可能您需要创建自己的流类来验证其位置并返回所需的子集 我不知道有任何内置类可以这样做。你到底害怕复制什么?我怀疑你是否有任何超性能的关键,动态解析你的流,并使用MemoryStream,直到你发现你需要其他东西 看起来这个项

我有一个包含许多数据片段的流。我只想在另一个流中公开该数据的一部分。我要提取的数据块通常可以超过100mb。因为我已经有了包含数据的流,所以将该数据复制到另一个流并返回该数据似乎是一种浪费。我要寻找的是一种在控制第二个流可以引用多少数据的同时引用第一个流中的数据的方法。这是否可能

您需要创建自己的流类来验证其位置并返回所需的子集


我不知道有任何内置类可以这样做。

你到底害怕复制什么?我怀疑你是否有任何超性能的关键,动态解析你的流,并使用MemoryStream,直到你发现你需要其他东西

看起来这个项目是出于类似的目的而创建的。

Mark Gravell很好地实现了这一点。张贴在那里的代码是:

using System.IO;
using System;
static class Program
{

 // shows that we can read a subset of an existing stream...
    static void Main()
    {
        byte[] buffer = new byte[255];
        for (byte i = 0; i < 255; i++)
        {
            buffer[i] = i;
        }
        using(MemoryStream ms = new MemoryStream(buffer))
        using (SubStream ss = new SubStream(ms, 10, 200))
        {
            const int BUFFER_SIZE = 17; // why not...
            byte[] working = new byte[BUFFER_SIZE];
            int read;
            while ((read = ss.Read(working, 0, BUFFER_SIZE)) > 0)
            {
                for (int i = 0; i < read; i++)
                {
                    Console.WriteLine(working[i]);
                }
            }
        }
    }
}

class SubStream : Stream
{
    private Stream baseStream;
    private readonly long length;
    private long position;
    public SubStream(Stream baseStream, long offset, long length)
    {
        if (baseStream == null) throw new ArgumentNullException("baseStream");
        if (!baseStream.CanRead) throw new ArgumentException("can't read base stream");
        if (offset < 0) throw new ArgumentOutOfRangeException("offset");

        this.baseStream = baseStream;
        this.length = length;

        if (baseStream.CanSeek)
        {
            baseStream.Seek(offset, SeekOrigin.Current);
        }
        else
        { // read it manually...
            const int BUFFER_SIZE = 512;
            byte[] buffer = new byte[BUFFER_SIZE];
            while (offset > 0)
            {
                int read = baseStream.Read(buffer, 0, offset < BUFFER_SIZE ? (int) offset : BUFFER_SIZE);
                offset -= read;
            }
        }
    }
    public override int Read(byte[] buffer, int offset, int count)
    {
        CheckDisposed();
        long remaining = length - position;
        if (remaining <= 0) return 0;
        if (remaining < count) count = (int) remaining;
        int read = baseStream.Read(buffer, offset, count);
        position += read;
        return read;
    }
    private void CheckDisposed()
    {
        if (baseStream == null) throw new ObjectDisposedException(GetType().Name);
    }
    public override long Length
    {
        get { CheckDisposed(); return length; }
    }
    public override bool CanRead
    {
        get { CheckDisposed(); return true; }
    }
    public override bool CanWrite
    {
        get { CheckDisposed(); return false; }
    }
    public override bool CanSeek
    {
        get { CheckDisposed(); return false; }
    }
    public override long Position
    {
        get {
            CheckDisposed();
            return position;
        }
        set { throw new NotSupportedException(); }
    }
    public override long Seek(long offset, SeekOrigin origin)
    {
        throw new NotSupportedException();
    }
    public override void SetLength(long value)
    {
        throw new NotSupportedException();
    }
    public override void Flush()
    {
        CheckDisposed(); baseStream.Flush();
    }
    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
        if (disposing)
        {
            if (baseStream != null)
            {
                try { baseStream.Dispose(); }
                catch { }
                baseStream = null;
            }
        }
    }
    public override void Write(byte[] buffer, int offset, int count)
    {
        throw new NotImplementedException();
    }
}
使用System.IO;
使用制度;
静态类程序
{
//显示我们可以读取现有流的子集。。。
静态void Main()
{
字节[]缓冲区=新字节[255];
用于(字节i=0;i<255;i++)
{
缓冲区[i]=i;
}
使用(MemoryStream ms=新的MemoryStream(缓冲区))
使用(子流ss=新子流(ms,10200))
{
const int BUFFER_SIZE=17;//为什么不。。。
字节[]工作=新字节[缓冲区大小];
int-read;
而((read=ss.read(工作,0,缓冲区大小))>0)
{
for(int i=0;i0)
{
int read=baseStream.read(缓冲区,0,偏移量<缓冲区大小?(int)偏移量:缓冲区大小);
偏移量-=读取;
}
}
}
公共重写整型读取(字节[]缓冲区、整型偏移量、整型计数)
{
CheckDisposed();
剩余长度=长度-位置;

如果(剩余我还需要一个子流,以便我可以处理另一个文件中的ZIP存档,那么另一个答案没有实现查找,尽管这里有一个与查找有关的答案;请注意,在处理原始流时,它不会处理原始流:

public class SubStream : Stream
{
    Stream Vector;
    long Offset, _Length, _Position = 0;
    public SubStream(Stream vector, long offset, long length)
    {
        if (length < 1) throw new ArgumentException("Length must be greater than zero.");

        this.Vector = vector;
        this.Offset = offset;
        this._Length = length;

        vector.Seek(offset, SeekOrigin.Begin);
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        CheckDisposed();
        long remaining = _Length - _Position;
        if (remaining <= 0) return 0;
        if (remaining < count) count = (int)remaining;
        int read = Vector.Read(buffer, offset, count);
        _Position += read;
        return read;
    }

    private void CheckDisposed()
    {
        if (Vector == null) throw new ObjectDisposedException(GetType().Name);
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        long pos = _Position;

        if (origin == SeekOrigin.Begin)
            pos = offset;
        else if (origin == SeekOrigin.End)
            pos = _Length + offset;
        else if (origin == SeekOrigin.Current)
            pos += offset;

        if (pos < 0) pos = 0;
        else if (pos >= _Length) pos = _Length - 1;

        _Position = Vector.Seek(this.Offset + pos, SeekOrigin.Begin) - this.Offset;

        return pos;
    }

    public override bool CanRead => true;

    public override bool CanSeek => true;

    public override bool CanWrite => false;

    public override long Length => _Length;

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

    public override void Flush()
    {
        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();
    }
}
公共类子流:流
{
流向量;
长偏移量,_长度,_位置=0;
公共子流(流向量、长偏移、长长度)
{
如果(长度<1)抛出新的ArgumentException(“长度必须大于零”);
这个向量=向量;
这个偏移量=偏移量;
这个。_长度=长度;
vector.Seek(偏移量,SeekOrigin.Begin);
}
公共重写整型读取(字节[]缓冲区、整型偏移量、整型计数)
{
CheckDisposed();
剩余长度=_长度-_位置;
如果(剩余=_长度)位置=_长度-1;
_Position=Vector.Seek(this.Offset+pos,参见korigin.Begin)-this.Offset;
返回pos;
}
public override bool CanRead=>true;
public override bool CanSeek=>true;
公共覆盖boolcanwrite=>false;
公共覆盖长长度=>\u长度;
公共重写长位置{get=>\u Position;set{\u Position=this.Seek(value,SeekOrigin.Begin);}
公共覆盖无效刷新()
{
抛出新的NotImplementedException();
}
公共覆盖无效设置长度(长值)
{
抛出新的NotImplementedException();
}
公共重写无效写入(字节[]缓冲区、整数偏移量、整数计数)
{
抛出新的NotImplementedException();
}
}

我会复制数百个MESG值的数据,不想将其复制到内存中的另一个位置。特别是如果该人要请求数百个meg节。此外,这不是担心重复,是一种编程实践,以重用其他类(如果它们存在)。这看起来不错。我希望代码项目能够成功h Git Hub。可能存在轻微的利益冲突。