Read specific bytes of a file

49,171

Solution 1

LINQ Version:

byte[] test = File.ReadAllBytes(file).Skip(50).Take(10).ToArray();

Solution 2

Create a BinaryReader, read 10 bytes starting at byte 50:

byte[] test = new byte[10];
using (BinaryReader reader = new BinaryReader(new FileStream(file, FileMode.Open)))
{
    reader.BaseStream.Seek(50, SeekOrigin.Begin);
    reader.Read(test, 0, 10);
}

Solution 3

This should do it

var data = new byte[10];
int actualRead;

using (FileStream fs = new FileStream("c:\\MyFile.bin", FileMode.Open)) {
    fs.Position = 50;
    actualRead = 0;
    do {
        actualRead += fs.Read(data, actualRead, 10-actualRead);
    } while (actualRead != 10 && fs.Position < fs.Length);
}

Upon completion, data would contain 10 bytes between file's offset of 50 and 60, and actualRead would contain a number from 0 to 10, indicating how many bytes were actually read (this is of interest when the file has at least 50 but less than 60 bytes). If the file is less than 50 bytes, you will see EndOfStreamException.

Solution 4

You need to:

  • seek to the data you want
  • call Read repeatedly, checking the return value, until you have all the data you need

For example:

public static byte[] ReadBytes(string path, int offset, int count) {
    using(var file = File.OpenRead(path)) {
        file.Position = offset;
        offset = 0;
        byte[] buffer = new byte[count];
        int read;
        while(count > 0  &&  (read = file.Read(buffer, offset, count)) > 0 )
        {
            offset += read;
            count -= read;
        }
        if(count < 0) throw new EndOfStreamException();
        return buffer;     
    }
}

Solution 5

using System.IO;

public static byte[] ReadFile(string filePath)
{
    byte[] buffer;
    FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
    try
    {
        buffer = new byte[length];            // create buffer
        fileStream.Read(buffer, 50, 10);
     }
     finally
     {
         fileStream.Close();
     }
     return buffer;
 }
Share:
49,171
Ahmed M. Taher
Author by

Ahmed M. Taher

Updated on July 26, 2021

Comments

  • Ahmed M. Taher
    Ahmed M. Taher almost 3 years

    Is there any way to read specific bytes from a file?

    For example, I have the following code to read all the bytes of the file:

    byte[] test = File.ReadAllBytes(file);
    

    I want to read the bytes from offset 50 to offset 60 and put them in an array.

  • Mesh
    Mesh over 12 years
    ONLY because you edited the question...In the OP this was not clear.
  • Marc Gravell
    Marc Gravell over 12 years
    You are meant to always check the return value of Read and loop as necessary. It is legal for Read to return 1 even when another 20000 bytes are available.
  • Richard
    Richard over 12 years
    I suggest you look at my edit. The file requirement was there (and I didn't change the title).
  • Marc Gravell
    Marc Gravell over 12 years
    The "offset" in the call to Read is the offset in the buffer, not the offset in the stream
  • oqx
    oqx over 12 years
    numBytesRead is the offset, the arguments goes (buffer,offset,count)
  • Marc Gravell
    Marc Gravell over 12 years
    From FilStream.Read on MSDN: " An implementation is free to return fewer bytes than requested even if the end of the stream has not been reached."
  • Richard
    Richard over 12 years
    On the other hand, the second param of FileStream.Read is the offset into the array passed as the first parameter and not the offset in the file. So actually I was correct! :-) (As it stands the code will throw because index 50 is beyond the end of bytes.)
  • Marc Gravell
    Marc Gravell over 12 years
    The important thing is: the documentation explicitly reserved that right: so - I you don't, you aren't following the published API
  • the_joric
    the_joric over 12 years
    Here all file content will be read and then only 10 bytes will be used. Not very optimal approach :)
  • Marc Gravell
    Marc Gravell over 12 years
    you still aren't updating pos correctly; imagine it returns 1 byte each time... That means you overrwrite offset 1 each time (except the first) and tell it to read to much data (10 - pos)
  • Richard
    Richard over 12 years
    @the_joric However a helper that given a filename returned a lazy IEnumerable<byte> in place of File.ReadAllBytes would be an effective approach, especially if reading an arbitrary run of bytes from a file was a common need.
  • Tajomaru
    Tajomaru almost 11 years
    Stream.Seek method takes two arguments. It should be reader.BaseStream.Seek(50, SeekOrigin.Begin);
  • Nick Falco
    Nick Falco about 9 years
    Worked great! Thanks!
  • Phil Whittington
    Phil Whittington about 6 years
    @Richard -- not really. The Linq Skip method still iterates through those bytes; it just doesn't doesn't "yield" them up to the callng method. You really want to make a request to read from the offset directly. Using bespoke API calls for each OS will be the fastest solution, although the questioner may want a pure .Net approach for peace of mind.
  • Richard
    Richard about 6 years
    @PhilWhittington Won't matter in this case, everything is in the first block of the file, so there will be a single read of data from the file either way.
  • brthornbury
    brthornbury almost 6 years
    This is terrible, and defeats the entire purpose of reading from only part of the file.
  • Jee
    Jee almost 4 years
    Is it just me or is this the better answer?
  • Soleil
    Soleil over 3 years
    This solution does not allow multiple file access.
  • Soleil
    Soleil over 3 years
    Unlike Robert Rouhani'ssolution, this one do allow multiple file access.
  • Eli Davis
    Eli Davis about 2 years
    Answers like this are why LINQ has such a bad reputation for performance. 9 upvotes too meaning people have implemented this solution. Now there's some innocent-looking util function waiting to tank an application when it's requested to load in a small portion of a file, while the file itself is larger than the RAM of the computer. Poor one out for the homies having to debug that crash