Visual Studio Development Bookmark and Share   
 index > Visual C# Express Edition > Is there a more efficient way to convert Stream to byte array?
 

Is there a more efficient way to convert Stream to byte array?

I have a stream from the embedded resources that I need to convert to a byte array.
This is what I have

byte[] image = new byte[myStream.Length];
for (int i = 0; i < myStream.Length; i++)
{
     image[i] = (byte) myStream.ReadByte();
}


This works and does what I want to achieve. And efficiency isn't really a concern for this application.

However, out of curiosity, I would like to know if there is a better way of doing this.
xenoverse  Friday, October 09, 2009 11:59 PM
What matters it the cost of a method call vs the cost of copying a byte.  Copying the byte is very cheap, it usually takes only a few CPU instructions.  Making the call involves setting up the method arguments and calling the method, then doing a bunch of checks that verify if the arguments are valid inside the method.  Lots of CPU instructions.  You'll end up spending more time doing the calling than doing the copying.  When you copy chunks of, say, 4096 bytes, you'll make only 1/4096th as many calls.

Hans Passant.
  • Marked As Answer byxenoverse Tuesday, October 13, 2009 6:11 PM
  •  
nobugz  Tuesday, October 13, 2009 5:56 PM
Yes, definitely:

  byte[] image = new byte[myStream.Length];
  for (int copied = 0; copied < myStream.Length; ) {
    copied += myStream.Read(image, copied, myStream.Length - copied);
  }

Hans Passant.
nobugz  Saturday, October 10, 2009 12:06 AM
Yes.  Right now, you're reading byte by byte, which is slow.  If you batch it, it'll run much faster:

byte[] image = new byte[myStream.Length];
int bytesRead = 0;
int numBytesToRead = (int) myStream.Length;

while (numBytesToRead > 0)
{
     int read = myStream.Read(image, bytesRead, numBytesToRead);
     if (read == 0)
       break;
     numBytesToRead -= read;
     bytesRead += read;
}

myStream.Close();


Reed Copsey, Jr. - http://reedcopsey.com
Reed Copsey, Jr.  Saturday, October 10, 2009 12:08 AM
The embedded resource is returned as an UnmanagedMemoryStream.  You can use the PositionPointer property to get a byte* that you can work with in an "unsafe" code block.  This will let you copy the data directly from the resource's buffer to your byte array.  This requires that Your Project Properties, Build, Allow unsafe code is turned on.

I'm not sure why loading byte[]'s from resources is a bottleneck for your application.  Embedded resources really are not intended for huge files.  And if you need to convert the embedded resource multiple times, it might help to just to keep the same byte[] around.  So, the following code is mainly a curiousity.  I'm not necessarily recommending it because I think the root of your problems is elsewhere.

            System.IO.UnmanagedMemoryStream ums = (System.IO.UnmanagedMemoryStream)System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("WindowsFormsApplication1.EmbeddedResource1.txt");
            byte[] byteArray = new byte[ums.Length];
            unsafe
            {
                System.Runtime.InteropServices.Marshal.Copy(new IntPtr(ums.PositionPointer), byteArray, 0, (int)ums.Length);
            }
BinaryCoder  Saturday, October 10, 2009 12:32 AM
Hi BinaryCoder, thanks for your input. Loading byte[] from embedded resource isn't a bottleneck for my application. I was asking simply because I wanted to know if there is a better way of doing what I wanted to do. A for loop just seemed too "primitive". :)
xenoverse  Tuesday, October 13, 2009 4:35 PM
What's the difference between my for loop, which copies the array byte by byte and your for loop that uses the Stream.Read() function to copy the data into the buffer giving the start position and the number of units to copy? Is that because the Stream.Read() is already optimized?
xenoverse  Tuesday, October 13, 2009 4:37 PM
What's the difference between my for loop, which copies the array byte by byte and your for loop that uses the Stream.Read() function to copy the data into the buffer giving the start position and the number of units to copy? Is that because the Stream.Read() is already optimized?

Yes.  When you use Stream.Read, you'll read out of the stream in large chunks.  Most stream implementations buffer internally, and you can usually read the entire buffer in one shot.

Profile it to see the difference.  I've seen, with some stream implementations, nearly 100x speed improvements when reading using Read(...) with a block vs. reading byte by byte.

 

Reed Copsey, Jr. - http://reedcopsey.com
Reed Copsey, Jr.  Tuesday, October 13, 2009 4:50 PM
What matters it the cost of a method call vs the cost of copying a byte.  Copying the byte is very cheap, it usually takes only a few CPU instructions.  Making the call involves setting up the method arguments and calling the method, then doing a bunch of checks that verify if the arguments are valid inside the method.  Lots of CPU instructions.  You'll end up spending more time doing the calling than doing the copying.  When you copy chunks of, say, 4096 bytes, you'll make only 1/4096th as many calls.

Hans Passant.
  • Marked As Answer byxenoverse Tuesday, October 13, 2009 6:11 PM
  •  
nobugz  Tuesday, October 13, 2009 5:56 PM

You can use google to search for other answers

Custom Search

More Threads

• XMLReader problems ...
• WM Player -My Playlists- Not playing!
• Writea program
• Problem with Convert.Int32("string num")
• PictureBox, Image, local resource, project resource file, Form1.resx
• Microsoft® Visual C#® 2005 Express Edition: Build a Program Now!
• C# Server Tips?
• Help for F#
• disable the hyperlink of tree view control in asp.net2.0
• how to increase my app versioin