Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is GetBuffer() on MemoryStream ever useful?

I've known that GetBuffer() on a MemoryStream in C#/.NET has to be used with care, because, as the docs describe here, there can be unused bytes at the end, so you have to be sure to look only at the first MemoryStream.Length bytes in the buffer.

But then I ran into a case yesterday where bytes at the beginning of the buffer were junk! Indeed, if you use a tool like reflector and look at ToArray(), you can see this:

public virtual byte[] ToArray() {     byte[] dst = new byte[this._length - this._origin];     Buffer.InternalBlockCopy(this._buffer, this._origin, dst, 0,         this._length - this._origin);     return dst; } 

So to do anything with the buffer returned by GetBuffer(), you really need to know _origin. The only problem is that _origin is private and there's no way to get at it...

So my question is - what use is GetBuffer() on a MemoryStream() without some apriori knowledge of how the MemoryStream was constructed (which is what sets _origin)?

(It is this constructor, and only this constructor, that sets origin - for when you want a MemoryStream around a byte array starting at a particular index in the byte array:

public MemoryStream(byte[] buffer, int index, int count, bool writable, bool publiclyVisible) 

)

like image 744
aggieNick02 Avatar asked Oct 24 '12 16:10

aggieNick02


People also ask

What is MemoryStream used for?

MemoryStream encapsulates data stored as an unsigned byte array. The encapsulated data is directly accessible in memory. Memory streams can reduce the need for temporary buffers and files in an application. The current position of a stream is the position at which the next read or write operation takes place.

What is the difference between Stream and MemoryStream?

You would use the FileStream to read/write a file but a MemoryStream to read/write in-memory data, such as a byte array decoded from a string. You would not use a Stream in and of itself, but rather use it for polymorphism, i.e. passing it to methods that can accept any implementation of Stream as an argument.

How do I reuse MemoryStream?

You can re-use the MemoryStream by Setting the Position to 0 and the Length to 0. By setting the length to 0 you do not clear the existing buffer, it only resets the internal counters.

Does MemoryStream copy byte array?

From expirience I can say, that it does not copy the array. Be aware though, that you are unable to resize the memory stream, when using an array in the constructor.


2 Answers

The answer is in the GetBuffer() MSDN doc, you might have missed it.

When you create a MemoryStream without providing a byte array (byte[]) :

it creates an expandable capacity initialized to zero.

In other words, the MemoryStream will reference to a byte[] with the proper size when a Write call will be made on the Stream.

Thus, with GetBuffer() you can directly access the underlying array and read to it.

This could be useful when you're in the situation that you will receive a stream without knowing its size. If the stream received is usually very big, it will be much faster to call GetBuffer() than calling ToArray() which copy the data under the hood, see below.

To obtain only the data in the buffer, use the ToArray method; however, ToArray creates a copy of the data in memory.

I wonder at which point you might have called GetBuffer() to get junk data at the beginning, it could be between two Write calls where the data from the first one would have been garbage collected, but I'm not sure if that could happen.

like image 166
ForceMagic Avatar answered Sep 23 '22 14:09

ForceMagic


If you really want to access the internal _origin Value, you may use the MemoryStream.Seek(0, SeekOrigin.Begin) call. The return Value will be exactly the _origin Value.

like image 34
marian.pascalau Avatar answered Sep 25 '22 14:09

marian.pascalau