C# Seek File Examples: ReadBytes

Call the Seek method on streams. Use BinaryReader and File.Open.

Seek locates a position in a file. It allows data to be read from a binary file at a certain part. For example, we can read 20,000 bytes from any part of a file. This is useful for certain file formats—particularly binary ones.File

Example. To begin our tutorial, we use the Seek method. From databases, you know that Seek is the term for when the data can be instantly retrieved, with an index. Therefore, Seek should be fast.
Here: This example gets the 50000th byte to the 51999th byte and iterates through them.
Note: The BinaryReader class is used. The program opens the binary file with BinaryReader here. It uses the "perls.bin" file.
C# program that seeks in Main method using System; using System.IO; class Program { static void Main() { // 1. // Open as binary file. using (BinaryReader b = new BinaryReader(File.Open("perls.bin", FileMode.Open))) { // 2. // Important variables: int length = (int)b.BaseStream.Length; int pos = 50000; int required = 2000; int count = 0; // 3. // Seek the required index. b.BaseStream.Seek(pos, SeekOrigin.Begin); // 4. // Slow loop through the bytes. while (pos < length && count < required) { byte y = b.ReadByte(); // 5. // Increment the variables. pos++; count++; } } } }

Variables used in program. Length is the entire length of the file we are reading from. Pos is the index we want to start reading from. Required is the number of bytes we want to read. Count is the number of bytes we have read.
Seek: We call Seek on the BaseStream and move the position to 50000 bytes. It looks through each byte.
Warning: The above code can slow down IO. It apparently requires each byte to be read separately off the disk.

Example 2. We next use the Seek method with arrays of bytes. There are two useful methods you can call to read in an array of bytes. They are Read and ReadBytes. We see ReadBytes, but if you need to reuse your buffer, use Read.
Here: The example opens the same binary file. We start at the same index in the file as the previous example (the 50000th byte).
Info: BinaryReader itself doesn't provide Seek, but you can use BaseStream with no damage.
And: It calls ReadBytes. This reads in the 2000 required bytes. These are stored in the byte array.
Note: If there aren't enough bytes left, the ReadBytes method does not throw exceptions.
C# program that uses Seek and ReadBytes using System; using System.IO; class Program { static void Main() { // 1. // Open file with a BinaryReader. using (BinaryReader b = new BinaryReader(File.Open("perls.bin", FileMode.Open))) { // 2. // Variables for our position. int pos = 50000; int required = 2000; // 3. // Seek to our required position. b.BaseStream.Seek(pos, SeekOrigin.Begin); // 4. // Read the next 2000 bytes. byte[] by = b.ReadBytes(required); } } }

Reusing buffers. The above code could be changed so you can provide your own buffer. This could cut down on memory usage and memory pressure in some situations. In a performance-sensitive application, this makes sense.

Discussion. Here we look at two Read methods available on the BinaryReader class. They both will store the result in an array but with the Read method you can provide your own buffer, which can reduce memory usage in some scenarios.
BinaryReader.ReadBytes: Reads count bytes from the current stream into a byte array and advances the current position by count bytes.
ReadBytes: Microsoft Docs
BinaryReader.Read: Reads count bytes from the stream with index as the starting point in the byte array.
Read: Microsoft Docs

Benchmarks. Here we compare the performance benchmarks of the first example shown in this article (which uses single byte reads) and the second example in this article (which uses arrays). The array example is much faster.
Note: This may occur because Windows doesn't buffer the single byte reads well. Also, there are different layers of code here.
Benchmark notes for Seek Bytes read: 20000 File size: 2.94 MB Start position: Inclusive random number Compilation: Release Iterations: 10000 Seek benchmark results Read one byte: 2574 ms Read array: 671 ms

Summary. We used the Seek method on the BinaryReader and FileStream classes. The article showed the performance of using seeking with BinaryReader and FileStream. Using the array read method is far faster than using single bytes.
Finally: In my test with a three megabyte file, the amount of time executing the Seek wasn't significant.

© 2007-2020 Sam Allen. Every person is special and unique. Send bug reports to info@dotnetperls.com.