If I did this in my MAUI project:
var uploadImage = new UploadImage();
var img = await uploadImage.OpenMediaPickerAsync();
var imagefile = await uploadImage.Upload(img);
var imageBytes = uploadImage.StringToByteBase64(imagefile.byteBase64);
var stream = uploadImage.ByteArrayToStream(imageBytes);
img_profilePic.Source = ImageSource.FromStream(() => stream); //working
I am displaying an image from my ios simulator. At one point in time I have the stream of the IO at my displosal.
If I now add
MemoryStream newStream = new MemoryStream();
stream.CopyTo(newStream);
these two lines of code to my code above, the image I was displaying at that point dissapears.
SO somehow, when I copy my stream, I for some reason also delete the already existing stream...?
What is going on here...
The point of streams is to be able to process very large amounts of data (sequentially) without having to load all that data into memory (at once anyway), which is what happens if instead of streams you work with collections. So, what stream do is track the current position so they can keep loading more data to memory when the position moves forward and unload already processed data. So, using the same stream for two things it's not going to work because the second usage won't get the data that the first usage has already consumed.
That said, it's possible to reset the position of a stream with the seek operation (as long as the type of stream you are using allows it).
Check out this answer https://stackoverflow.com/a/1746108/352826
SO somehow, when I copy my stream, I for some reason also delete the already existing stream...?
It's far more likely that you're trying to use the same stream as multiple sources without rewinding it. Streams have a position that increases as you use it.
In short, use this when you want to reuse your stream:
stream.Position = 0;
Assuming, of course, that whatever stream you're using is rewindable in the first place. If not, then copy it to a memory stream first and reuse that as many times as you wish, rewinding between uses.
Related
I receive a fair amount of binary data from an external device, about 30-40 MB/s. I need to save it to a file. On the external source device side, I have a very small buffer that I can't enlarge and as soon as the transmission stutters on the C# application side, it quickly gets clogged and I lose data.
In the application, I tried writing using FileStream, but unfortunately it is not fast enough.
_FileStream = new FileStream(FileName, FileMode.Create, FileAccess.Write);
...
void Handler_OnFtdiBytesReceived(object sender, FtdiBytesReceivedEventArgs e)
{
...
Array.Copy(e.Bytes, 0, _ReceivedDataBuffer, _ReceivedDataBufferPosition, e.NumBytesAvailable);
_ReceivedDataBufferPosition += (int)e.NumBytesAvailable;
if (_ReceivedDataBufferPosition > 0)
{
_FileStream.Write(_ReceivedDataBuffer, 0, (int)e.NumBytesAvailable);
_ReceivedDataBufferPosition = 0;
}
if (_IsOperationFinished == true)
{
_FileStream.Flush();
_FileStream.Close();
}
...
}
I also tried adding a BinaryWriter:
_FileStream = new FileStream(FileName, FileMode.Create, FileAccess.Write);
_BinaryWriter = new BinaryWriter(_FileStream);
and then:
_BinaryWriter.Write(_ReceivedDataBuffer, 0, (int)e.NumBytesAvailable);
instead of previous _FileStream.Write(...), but also the buffer on the transmit side gets clogged.
Is there any way to deal with this?
I wonder if it might help to somehow buffer the data in the computer's RAM when receiving it and, for example, when it reaches some sizable amount (say, 512 MB), start writing to the file in a separate Task, so that in the meantime, new data can be collected into the buffer continuously. Perhaps I would need to use two buffers and use them alternately, one to receive data continuously and the other from which to write to the file, and swap??
This seems quite complex code for someone with little experience, which I don't know if it will help, so I'd like to ask you for a hint first.
I'll just add at the end that I have the ability to watch the buffer fill up in this external device and by commenting out this one line regarding writing:
_FileStream.Write(_ReceivedDataBuffer, 0, (int)e.NumBytesAvailable);
I see that the problem with its clogging disappears. Earlier I also analyzed whether other code fragments might be inefficient, such as Array.Copy(...) or passing parameters via Event, but it had no effect.
I'm currently trying to save video file from a Http response and my method seems to work fine except the processing time for large video (1 GB) takes too long to finish.
using (HttpWebResponse wresp = (HttpWebResponse)wreq.GetResponse())
using (Stream mystream = wresp.GetResponseStream())
{
using (var f = new FileStream(Path.Combine(#"D:/Games/", "Test1.mp4"), FileMode.Create, FileAccess.Write))
{
f.Position = 0;
await mystream.CopyToAsync(f);
}
}
Console.WriteLine("Finished");
I think maybe I can just read all the response before processing to copy it to my local storage.
Or is there any better way that help me to process the video more quickly?
Using a larger stream buffer size should help increase the performance of the CopyToAsync() operation. However, you will likely need to test a few different buffer sizes in order to find the ideal value.
In order to do this, you will need to use the following override of the Stream.CopyToAsync() method: CopyToAsync(Stream, Int32).
Additionally, the following similar question may help in your research/troubleshooting: How can I improve the performance of this CopyTo method?.
I am trying to load some filestream into a memorystream. The source stream could be any stram, but the focus here is the destination stream.
The source has more than 3Gb.
I tryed 4 different approaches to this.
1)fDest = new MemoryStream(); and then read 4K blocks into this. This takes forever com complete as the buffer must be resized on every step.
2)fDest = new MemoryStream(int.MaxValue); Got OutOfMemoryException on creation
3)fDest = new MemoryStream(1073741823); and then read 4K blocks into this. This loads fast but i get an OutOfMemory exception when the buffer needs to be resized.
4)fDest = new MemoryStream(1073741824);and then read 4K blocks into this. This works. The buffer resize is ok.
Can anyone point me some direction on why i got this behaviour with just one byte in diference on buffer size? I
Occasionally we need to copy huge files from one bucket to another in AWS S3. Whenever possible we use the CopyRequest to handle this operation all on AWS (since no round trip required back to the client). But sometimes we do not have the option to do this because we need to copy between 2 completely separate accounts which requires a GET and then a PUT.
Problems:
The response stream returned from the GET is not seekable so it cannot be passed to the PUT request and have it stream seamlessly from one to the other
Copying the response stream to an intermediary stream (MemoryStream) using CopyTo() and then passing that to the PUT operation works well but doesn't scale (large files will throw OutOfMemory exceptions)
So basically I need an intermediary stream that I can read/write to at the same time, basically I would read a chunk from the response stream and write it to my intermediary stream, meanwhile the PUT request is reading out the content and its just a seamless pass-thru sort of scenario.
I found this post on stackoverflow and it seemed promising at first but it still throws an OutOfMemory exception with large files.
.NET Asynchronous stream read/write
Anyone ever had to do something similar to this? How would you tackle it? Thanks in advcance
It's not clear why you would want to use MemoryStream. The Stream.CopyTo method in .NET 4 doesn't need to use an intermediate stream - it will just read into a local buffer of a fixed size, then write that buffer to the output stream, then read more data (overwriting the buffer) etc.
If you're not using .NET 4, it's easy to implement something similar, e.g.
public static void CopyTo(this Stream input, Stream output)
{
byte[] buffer = new byte[64 * 1024]; // 64K buffer
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, bytesRead);
}
}
I found this, but it uses a Queue internally, which the author notes is an order of magnitude slower than a MemoryStream.
http://www.codeproject.com/Articles/16011/PipeStream-a-Memory-Efficient-and-Thread-Safe-Stre
I keep hoping I'll find an official MS library solution, but it seems that this wheel hasn't been properly invented yet.
I've been playing around with what I thought was a simple idea. I want to be able to read in a file from somewhere (website, filesystem, ftp), perform some operations on it (compress, encrypt, etc.) and then save it somewhere (somewhere may be a filesystem, ftp, or whatever). It's a basic pipeline design. What I would like to do is to read in the file and put it onto a MemoryStream, then perform the operations on the data in the MemoryStream, and then save that data in the MemoryStream somewhere. I was thinking I could use the same Stream to do this but run into a couple of problems:
Everytime I use a StreamWriter or StreamReader I need to close it and that closes the stream so that I cannot use it anymore. That seems like there must be some way to get around that.
Some of these files may be big and so I may run out of memory if I try to read the whole thing in at once.
I was hoping to be able to spin up each of the steps as separate threads and have the compression step begin as soon as there is data on the stream, and then as soon as the compression has some compressed data available on the stream I could start saving it (for example). Is anything like this easily possible with the C# Streams? ANyone have thoughts as to how to accomplish this best?
Thanks,
Mike
Using a helper method to drive the streaming:
static public void StreamCopy(Stream source, Stream target)
{
byte[] buffer = new byte[8 * 1024];
int size;
do
{
size = source.Read(buffer, 0, 8 * 1024);
target.Write(buffer, 0, size);
} while (size > 0);
}
You can easily combine whatever you need:
using (FileStream iFile = new FileStream(...))
using (FileStream oFile = new FileStream(...))
using (DeflateStream oZip = new DeflateStream(outFile, CompressionMode.Compress))
StreamCopy(iFile, oZip);
Depending on what you are actually trying to do, you'd chain the streams differently. This also uses relatively little memory, because only the data being operated upon is in memory.
StreamReader/StreamWriter shouldn't have been designed to close their underlying stream -- that's a horrible misfeature in the BCL. But they do, they won't be changed (because of backward compatibility), so we're stuck with this disaster of an API.
But there are some well-established workarounds, if you want to use StreamReader/Writer but keep the Stream open afterward.
For a StreamReader: don't Dispose the StreamReader. It's that simple. It's harmless to just let a StreamReader go without ever calling Dispose. The only effect is that your Stream won't get prematurely closed, which is actually a plus.
For a StreamWriter: there may be buffered data, so you can't get away with just letting it go. You have to call Flush, to make sure that buffered data gets written out to the Stream. Then you can just let the StreamWriter go. (Basically, you put a Flush where you normally would have put a Dispose.)
Unless you're reading in streams bigger than your hard drive, I don't think you'll run out of memory:
http://blogs.msdn.com/ericlippert/archive/2009/06/08/out-of-memory-does-not-refer-to-physical-memory.aspx