My method gets MemoryStream as parameter. How can I know whether this MemoryStream is expandable?
MemoryStream can be created using an array using "new MemoryStream(byte[] buf)". This means that stream will have fixed size. You can't append data to it.
On other hand, stream can be created with no parameters using "new MemoryStream()". In this case you can append data to it.
Question: How can I know - can I safely append data in a current stream or I must create a new expandable stream and copy data to it?
You can do that using reflection:
static bool IsExpandable(MemoryStream stream)
{
return (bool)typeof(MemoryStream)
.GetField("_expandable", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)
.GetValue(stream);
}
I don't know if there's a cleaner/safer way to retrieve this information.
It's not actually a fixed size in a sense, better defined as "non-expandable" since it can still be truncated via SetLength, but anyway... Probably the best thing that you can do is always use an expandable stream, or if you don't control that aspect of the code... Perhaps try catch your attempt to expand the stream and if it fails, copy it over to a writable stream and recursively call the method again?
Related
I think the title sums it up. I'm trying to set the source of an image in Xamarin using a stream but the method asks for a Func<Stream> as a parameter. I could just wrap the stream with a method but I don't really know if this could cause future problems. In conclusion, I want to set the source of an image in Xamarin using a stream and I neither know or could find, how to do that.
This approach is usually used for some Lazy-Loading purposes.
That means, the Stream is not accessed in the moment of passing it to the function.
Instead the function for getting/creating the Stream is saved and is used when is needed.
For example for image it could be when the image should appear on the screen (to prevent consumption of resources when the image is not visible).
So it's better to create the function that will create new Stream rather than keeping the opened stream in memory.
Example:
ImageSource.FromStream(() => File.OpenRead(path));
I m trying to use System.Net.Http for POST requests. I m ok with HTTP response body being in memory but need to obtain MemoryStream for it. One way to do that would be to call HttpContent.GetAsByteArrayAsync() and wrap a MemoryStream on top of it, but I think this would require content to be copied into a separate byte array (since it returns Task of byte[]).
If the response body is already in some internal buffer in HttpContent, is it possible to create MemoryStream on top of that buffer, or return MemoryStream from HttpContent somehow and avoid copying to a separate byte array?
There is also HttpContent.GetAsStreamAsync(), but that returns regular Stream, not MemoryStream. Even though it is probably an instance of MemoryStream already, I suppose it is not safe or a good practice to cast the returned stream to MemoryStream? (since this is implementation detail that could change).
Is there any other way of doing this, or do i have no choice but to copy into byte[] first?
Thanks.
If you call LoadIntoBufferAsync first, ReadAsStreamAsync returns a readonly MemoryStream:
await req.Content.LoadIntoBufferAsync();
var stream = (MemoryStream) await req.Content.ReadAsStreamAsync();
If you call LoadIntoBufferAsync first, CopyToAsync can be used to populate a readonly MemoryStream:
var stream = new MemoryStream(req.Content.Headers.ContentLength);
await req.Content.LoadIntoBufferAsync((int)req.Content.Headers.ContentLength);
await req.Content.CopyToAsync(stream);
This implementation doesn't depend on side effects and is supported by the docs in all framework versions: https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpcontent.loadintobufferasync?view=netframework-4.6.2
Note: I tried to edit the above answer, but couldn't do it... So here you are.
Can I create a new BinaryWriter and write on a Stream, while the stream is already beeing used by another BinaryWriter?
I need to write some data recursively, but I would like to avoid passing a BinaryWriter to a method as a parameter, as I need to pass a Stream instead. So, each method that will write data on the stream may need to create its own BinaryWriter instance. But I don't know if this is right. For now, it works well on a FileStream, but I don't know if it could lead to unexpected results on the users machines.
I wrote a simple example of what I want to achieve. Is this use of the BinaryWriter wrong?
Example:
public Main()
{
using (var ms = new MemoryStream())
{
// Write data on the stream.
WriteData(ms);
}
}
private void WriteData(Stream output)
{
// Create and use a BinaryWriter to use only on this method.
using (var bWriter = new BinaryWriter(output, Encoding.UTF8, true))
{
// Write some data using this BinaryWriter.
bWriter.Write("example data string");
// Send the stream to other method and write some more data there.
WriteMoreData(output);
// Write some more data using this BinaryWriter.
bWriter.Write("another example data string");
}
}
private void WriteMoreData(Stream output)
{
// Create and use a BinaryWriter to use only on this method.
using (var bWriter = new BinaryWriter(output, Encoding.Unicode, true))
{
// Write some data on this BinaryWriter.
bWriter.Write("write even more example data here");
}
}
Is this use of the BinaryWriter wrong?
It should work fine. BinaryWriter does no buffering itself, so each instance won't interfere with data written by other instances. You're passing true for the leaveOpen parameter, so when each instance is disposed, it won't close the underlying stream.
But "wrong" is to some degree in the eye of the beholder. I would say it's better to pass the BinaryWriter.
MemoryStream isn't buffered, but other types are. Each instance of BinaryWriter, when it's disposed, will flush the stream. This could be considered inefficient by some people, as it negates the benefit of the buffering, at least partially. Not an issue here, but may not be the best habit to get into.
In addition, each instance of BinaryWriter is going to create additional work for the garbage collector. If there's really only a few, that's probably not an issue. But if the real-world example involves a lot more calls, that could start to get noticeable, especially when the underlying stream is a MemoryStream (i.e. you're not dealing with some slow device I/O).
More to the point, I don't see any clear advantage to using multiple BinaryWriter instances on the same stream here. It seems like the natural, readable, easily-maintained thing to do would be to create a single BinaryWriter and reuse it until you're done writing.
Why do you want to avoid passing it as a parameter? You're already passing the Stream. Just pass the BinaryWriter instead. If you ever did need direct access to the underlying stream, it's always available via BinaryWriter.BaseStream.
Bottom line: I can't say there's anything clearly wrong per se with your proposal. But it's a deviation from normal conventions without (to me, anyway) a clear benefit. If you have a really good rationale for doing it this way, it should work. But I'd recommend against it.
I have always wondered what the best practice for using a Stream class in C# .Net is. Is it better to provide a stream that has been written to, or be provided one?
i.e:
public Stream DoStuff(...)
{
var retStream = new MemoryStream();
//Write to retStream
return retStream;
}
as opposed to;
public void DoStuff(Stream myStream, ...)
{
//write to myStream directly
}
I have always used the former example for sake of lifecycle control, but I have this feeling that it a poor way of "streaming" with Stream's for lack of a better word.
I would prefer "the second way" (operate on a provided stream) since it has a few distinct advantages:
You can have polymorphism (assuming as evidenced by your signature you can do your operations on any type of Stream provided).
It's easily abstracted into a Stream extension method now or later.
You clearly divide responsibilities. This method should not care on how to construct a stream, only on how to apply a certain operation to it.
Also, if you're returning a new stream (option 1), it would feel a bit strange that you would have to Seek again first in order to be able to read from it (unless you do that in the method itself, which is suboptimal once more since it might not always be required - the stream might not be read from afterwards in all cases). Having to Seek after passing an already existing stream to a method that clearly writes to the stream does not seem so awkward.
I see the benefit of Streams is that you don't need to know what you're streaming to.
In the second example, your code could be writing to memory, it could be writing directly to file, or to some network buffer. From the function's perspective, the actual output destination can be decided by the caller.
For this reason, I would prefer the second option.
The first function is just writing to memory. In my opinion, it would be clearer if it did not return a stream, but the actual memory buffer. The caller can then attach a Memory Stream if he/she wishes.
public byte[] DoStuff(...)
{
var retStream = new MemoryStream();
//Write to retStream
return retStream.ToArray();
}
100% the second one. You don't want to make assumptions about what kind of stream they want. Do they want to stream to the network or to disk? Do they want it to be buffered? Leave these up to them.
They may also want to reuse the stream to avoid creating new buffers over and over. Or they may want to stream multiple things end-to-end on the same stream.
If they provide the stream, they have control over its type as well as its lifetime. Otherwise, you might as well just return something like a string or array. The stream isn't really giving you any benefit over these.
I am working on a parser that watches a stream (probably from a NetworkStream). When certain data is seen on the source stream, a new MemoryStream is created and the relevant data from the source is written to it.
Then I pass the MemoryStream for parsing to another class method that parses the MemoryStream as a Stream. In this method a BinaryReader is created. When it goes to read the data there is none because the BinaryReader is actually at the end of the data.
The BinaryReader does not have a Position property or Seek method, so the underlining BaseStream position needs to be changed. Once the position is changed the stream can be parsed.
In this case we are not adding additional data so there is no problem. But the thought occurs to me that if a similar situation arrives and additional data is going to be written to the this might not work because the position value was changed behind its back.
I’m a bit fuzzy on the implications here.
Do the writer and reader work with copies of the BaseStream and its position or the original object allowing for corruption?
Does this mean that I need to create the reader at the same time I create the writer so that both start at the same spot then pass then reader to the method instead of the BaseStream? I think this might be a better practice.
Does the BinaryReader and Writer maintain their own position information? I'm thing not because the property isn't there. If not can you use them concurrently in the same thread?
Update #1: Based on an answer and comments that have since been withdrawn I think I need to make my confusion a little clearer.
There is a BaseStream property in both BinaryWriter and BinaryReader. I thought it pointed to the stream object that was used to create the writer and reader. I’m starting to think it is just a worker object that is unique to both.
I don’t want to assume to much about the stream objects so that I remain open to multiple types of streams as a source.
Update #2: Now after running some test code I see that they are connected. When data is written it affects the position of the reader. I would have thought to be useful the reader would remain unaffected so that it could pick up where it left off, reading the next part of the stream.
I envisioned something like this:
A data event occurs. The event causes data to be written by the writer.
At some point the reader works on some of the data in the stream.
Another event occurs causing more data to be written.
It is appended to the data that the reader already is working on.
The reader finishes its work including new data.
But based on the way the position works between the reader and writer this is not the way the stream is to be used,.
Maybe my conception problem is because my BaseStream is a MemoryStream and the rules are different than it would be with a NetworkStream. I was trying to keep the implementation details of the stream's source out of the reading class.
I guess at this point I have the answer to the question. Now I need to find information on using streams to do the type of thing that I have in my head.
I found that working with MemoryStream the Reader and Writer updated the position in the base stream. Therefore you cannot read a stream that is still being written without juggling copying and restoring of the position value. Not recommended.
I reworked things so that I could write an entire transaction to a MemoryStream pass it to another class. The create a new MemoryStream for the next transaction.
The base stream is not a derivation of the given stream, it is the actual stream.