11

Until now I am counting 12 LoCs. Could you make it smaller?

using (Stream fileStream = File.OpenRead(fileName))
{
    using (BinaryReader binaryReader = new BinaryReader(fileStream))
    {
        using (MemoryStream memoryStream = new MemoryStream())
        {
            byte[] buffer = new byte[256];
            int count;
            int totalBytes = 0;
            while ((count = binaryReader.Read(buffer, 0, 256)) > 0)
            {
                memoryStream.Write(buffer, 0, count);
                totalBytes += count;
            }
            memoryStream.Position = 0;
            byte[] transparentPng = new byte[totalBytes];
            memoryStream.Read(transparentPng, 0, totalBytes);
        }
    }
}

5 Answers 5

30

There's a static method that can do this for you in one call.

var data = File.ReadAllBytes(fileName);

Alternatively, a method that works for any Stream (that returns its length) would be:

byte[] data;
using (var br = new BinaryReader(stream))
    data = br.ReadBytes((int)stream.Length);

For streams that don't have a well-defined length (e.g. NetworkStream), and thus raise an exception on calling stream.Length, this of course does not work. The slightly more complicated solution presented in Jon Skeet's answer is then what you probably want.

Sign up to request clarification or add additional context in comments.

3 Comments

data = binaryReader.ReadBytes(stream.Length); should be data = br.ReadBytes(stream.Length);
did anyone try this? br.ReadBytes takes an int param and stream.Length is a long. It won't compile.
It's easily fixed by a simple cast though. In the case where the length of the stream is longer than the maximum Int32 value, you really don't want to be doing this anyway!
27

How 'bout one:

byte[] result = File.ReadAllBytes(fileName);

3 Comments

Although it only works for files of course... it matches the code in the original question, but not the title of the question :)
Good point. Maybe if I get bored later I'll express this in terms of a function that accepts an open stream as input - for all the code snippets no one's bothered to put a function signature out yet.
It isn't much more complicated for a stream whose length you know, as I demonstrate in my answer. For a stream of unknown length, you could probably write a 3/4 line extension method that does the job.
19

Reducing your lines of code is pretty simple here (while still working with arbitrary streams, rather than just files):

using (Stream fileStream = File.OpenRead(fileName))
using (MemoryStream memoryStream = new MemoryStream())
{
    int byteRead;
    while ((byteRead = fileStream.ReadByte()) != -1)
    {
        memoryStream.WriteByte(byteRead);
    }
    return memoryStream.ToArray();
}

Obviously it's a lot more efficient to read into a buffer than to read a byte at a time, but this reduces the number of statements (as you don't need to declare both a buffer and a variable to hold the return value from Stream). Calling MemoryStream.ToArray() is simpler than reading into a newly constructed array.

Using a buffer is nicer though. Note that we really don't need BinaryReader:

using (Stream fileStream = File.OpenRead(fileName))
using (MemoryStream memoryStream = new MemoryStream())
{
    byte[] buffer = new byte[8192];
    int bytesRead;
    while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0)
    {
        memoryStream.Write(buffer, 0, bytesRead);
    }
    return memoryStream.ToArray();
}

If you want to be really brutal, we could reduce the number of using statements (with either solution):

using (Stream fileStream = File.OpenRead(fileName),
              memoryStream = new MemoryStream())
{
    byte[] buffer = new byte[8192];
    int bytesRead;
    while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0)
    {
        memoryStream.Write(buffer, 0, bytesRead);
    }
    return ((MemoryStream)memoryStream).ToArray();
}

But that's just nasty :)

Another option of course is to use a library such as MiscUtil which has a method to read fully from a stream :) The utility method can be as simple as this:

public static byte[] ReadFully(this Stream stream)
{
    using (MemoryStream memoryStream = new MemoryStream())
    {
        byte[] buffer = new byte[8192];
        int bytesRead;
        while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
        {
            memoryStream.Write(buffer, 0, bytesRead);
        }
        return memoryStream.ToArray();
    }
}

Note that this never closes the stream - the caller should do that.

Comments

8

While not reducing the LOC (I'd never use this as a primary motivation), you can collapse the usings like this:

using (Stream fileStream = File.OpenRead(fileName))
using (BinaryReader binaryReader = new BinaryReader(fileStream))
using (MemoryStream memoryStream = new MemoryStream())
{
    byte[] buffer = new byte[256];
    int count;
    int totalBytes = 0;
    while ((count = binaryReader.Read(buffer, 0, 256)) > 0)
    {
        memoryStream.Write(buffer, 0, count);
        totalBytes += count;
    }
    memoryStream.Position = 0;
    byte[] transparentPng = new byte[totalBytes];
    memoryStream.Read(transparentPng, 0, totalBytes);    
}

3 Comments

"why does that matter if it works?" It doesn't matter as long as you don't have to maintain the code ;-)
+1 for "why does it matter..." Sometimes the most concise isn't the most readable (or the most performant). In this case, though, File.ReadAllBytes is pretty hard to beat.
The point I was trying to make (badly) is that the goal shouldn't be to reduce the LOC but to increase clarity. I'd take 30 lines of clear code over 4 lines of obfusticated madness any day.
2

Just use the CopyTo method of the Stream to copy to a MemoryStream, and get the array:

using (var fileStream = File.OpenRead(fileName))
{
    using (var memoryStream = new MemoryStream())
    {
        fileStream.CopyTo(memoryStream);
        memoryStream.Seek(0, SeekOrigin.Begin);

        byte[] transparentPng = memoryStream.ToArray();
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.