Home > OS >  Create stream using byte array buffer
Create stream using byte array buffer

Time:01-20

I want to use a third party dll function which requires a stream input.

The data I need to feed it is provided by a different third party dll function, which only offers access to the source data by using a 'ReadBuffer' option to obtain chunks of data at a time, by populating a byte array of a set length.

The data I'm reading exceeds several TB, so I'm unable to just write a loop and write all the data to memory and then into a stream.

Is their a simple way to create a stream from data which is being read into a byte array buffer within a while loop as the stream is read?

I'm writing in C# & thanks for any pointers

Thanks

CodePudding user response:

You can use a MemoryStream in C# to create a stream using a byte array buffer. You can use the ReadBuffer method from the third party DLL to populate a byte array, and then use the Write method from the MemoryStream to write the byte array to the stream.

///
using (var memoryStream = new MemoryStream())
{
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = thirdPartyDll.ReadBuffer(buffer, 0, buffer.Length)) > 0)
{
    memoryStream.Write(buffer, 0, bytesRead);
}
}

You can use an extra BufferedStream to wrap around the MemoryStream and buffer more data, so you don't have to write each byte array to the stream one by one.

 ///
using (var memoryStream = new MemoryStream())
using (var bufferedStream = new BufferedStream(memoryStream))
{
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = thirdPartyDll.ReadBuffer(buffer, 0, buffer.Length)) > 0)
{
    bufferedStream.Write(buffer, 0, bytesRead);
}}

CodePudding user response:

You should inherit the Stream Class. It is possible your library offers all the data from an inner Stream you may read and set in your derived class (Current position, Data Length, if can be readed, etc).

This way you can create a new object and use in the other library

public class MyStream : Stream
{
    private LibraryClient _client;

    // Wrapper
    public MyStream(LibraryClient libraryClient)
    {
        buffer = new byte[bufferSize];
        _client = libraryClient;
    }

    // Return the client length
    public override long Length => _client.DataLength;
    

    // Specify the position in your buffer, if the client has this info, reference it
    public override long Position { get; set; }


    public override int Read(byte[] buffer, int offset, int count)
    {
        // temp array in local var for example. you may instance it or rent it as well
        var tmp = new byte[count - offset];

        _client.ReadBuffer(tmp, Position, count);

        //copy all (we skip count check because it's local variable)
        tmp.CopyTo(buffer, offset);
        return count - offset; //if the library 'ReadBuffer' returns the length readed, place it here

    }


    public override long Seek(long offset, SeekOrigin origin)
    {
        //... this method moves the Position of the Stream
        //use it to update the inner position
        if (offset > _client.DataLength) throw new ArgumentOutOfRangeException();
        long tempPosition = 0;
        switch (origin)
        {
            case SeekOrigin.Begin:
                {
                    tempPosition = offset;
                    break;
                }
            case SeekOrigin.Current:
                {
                    tempPosition = Position   offset;
                    Position = tempPosition;
                    break;
                }
            case SeekOrigin.End:
                {
                    tempPosition = _client.DataLength   offset;
                    break;
                }
        }

        if (tempPosition < 0) throw new IOException("Offset too backward");
        if (tempPosition > _client.DataLength) throw new IOException("Offset too foward");

        Position = tempPosition;

        return offset;
    }

    public override void SetLength(long value)
    {
        // ... handle if neccesary
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        // ... handle if neccesary
    }

    public override void Flush()
    {
        // handle if neccesary
    }

    // Modify if neccesary
    public override bool CanWrite => false;
    public override bool CanSeek => true;
    public override bool CanRead => Position < Length;
}
  • Related