Answered Binary File Read

AussieBoy

Well-known member
Joined
Sep 7, 2020
Messages
78
Programming Experience
Beginner
Hi,
I need to read in values from a binary file.
The header is made up of.
4 bytes, 1 byte, 1 byte, 2 bytes, 4 bytes, 4 bytes, 4 bytes
I have a int32, byte, byte, inst16, int32, int32, int32.
Which should read as 484 5 30 1595434298 15 58.
(However, it doesn't at the moment)
I had started off with Python, but need to switch to C# for other reasons.

the python code looked like

with open(filename, "rb") as file:
buffer = file.read(20)
size, variation, objectType, pointIndex, startTime, sampleRate, count = struct.unpack('>IBBHiII', buffer)
print(size, variation, objectType, startTime, sampleRate, count)

The start on C# is below.

C#:
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;


namespace InsertHistoryCOMAPI
{
       class Program
       {
             static void Main(string[] args)
             {
                    // Specifing a file
                    string path = @"C:\DNP3File\XXXXXXXXXX";

                    // Calling the ReadAllBytes() function
                    byte[] readText = File.ReadAllBytes(path);

                    byte[] temp;

                    int[] values = new int[3];

                    temp = new byte[4];
                    Array.Copy(readText, 0, temp, 0, 4);
                    values[0] = BitConverter.ToInt32(temp, 0);
                    Console.WriteLine(values[0]);

                    temp = new byte[4];
                    Array.Copy(readText, 4, temp, 0, 1);
                    values[0] = BitConverter.ToInt32(temp, 0);
                    Console.WriteLine(temp);

                    temp = new byte[4];
                    Array.Copy(readText, 5, temp, 0, 1);
                    values[0] = BitConverter.ToInt32(temp, 0);
                    Console.WriteLine(temp);

                    temp = new byte[4];
                    Array.Copy(readText, 6, temp, 0, 2);
                    values[0] = BitConverter.ToInt16(temp, 0);
                    Console.WriteLine(values[0]);

                    temp = new byte[4];
                    Array.Copy(readText, 8, temp, 0, 4);
                    values[0] = BitConverter.ToInt32(temp, 0);
                    Console.WriteLine(values[0]);

                    temp = new byte[4];
                    Array.Copy(readText, 12, temp, 0, 4);
                    values[0] = BitConverter.ToInt32(temp, 0);
                    Console.WriteLine(values[0]);

                    temp = new byte[4];
                    Array.Copy(readText, 16, temp, 0, 4);
                    values[0] = BitConverter.ToInt32(temp, 0);
                    Console.WriteLine(values[0]);

                    Console.ReadLine();
             }
 
Don't start by calling ReadAllBytes. Just read the bytes from the file as required. Try these methods:
C#:
private short ReadShort(Stream stream)
{
    var bytes = new byte[2];

    stream.Read(bytes, 0, 2);

    return BitConverter.ToInt16(bytes, 0);
}

private int ReadInt(Stream stream)
{
    var bytes = new byte[4];

    stream.Read(bytes, 0, 4);

    return BitConverter.ToInt32(bytes, 0);
}
and then use them like this:
C#:
using (var file = File.OpenRead(filePath))
{
    var b = (byte) file.ReadByte();
    var s = ReadShort(file);
    var i = ReadInt(file);
}
 
Thanks,

I changed it a little. as to below.
I get
-469696512
5
30
-26310
979703903
251658240
973078528
I am looking for
484 5 30 1595434298 15 58
Thanks,

C#:
using (var file = File.OpenRead(path))

            {

                var size = ReadInt(file);
                Console.WriteLine(size);

                var variation = (byte)file.ReadByte();
                Console.WriteLine(variation);

                var objectType = (byte)file.ReadByte();
                Console.WriteLine(objectType);

                var pointIndex = ReadShort(file);
                Console.WriteLine(pointIndex);

                var startTime = ReadInt(file);
                Console.WriteLine(startTime);

                var sampleRate = ReadInt(file);
                Console.WriteLine(sampleRate);

                var numberOfSamples = ReadInt(file);
                Console.WriteLine(numberOfSamples);

                Console.ReadLine();
            }
 
Hi, I think this will help.
It may need a pointer, so that it steps through and knows which byte(s) is next.
Thanks,

# Header = 20 words
# 32bit integer - Size
# 1 byte - Variation
# 1 byte - Object
# Object Variation
# 30 1 32-bit integer samples
# 30 2 16-bit integer samples
# 30 3 32-bit integer samples
# 30 4 16-bit integer samples
# 30 5 32-bit floating point samples
# 16bit unsigned integer - Point index, analog point index being sampled
# 32bit integer - Start Time EPOCH
# 32bit integer - Sample Rate, the interval (in seconds) between samples of the analog point
# 32bit integer - Number of Samples, the number of sample records in this file
# Size = 20 + (Number of Samples) * 4 - 16bit integer
# Size = 20 + (Number of Samples) * 8 - 32bit integer
 
00000000 00000000 00000001 11100100 00000101 00011110 00111010 10011001 01011111 00011000 01100101 00111010 00000000 00000000 00000000 00001111 00000000 00000000 00000000 00111010 00000000 00000000 00000000 00000000 01000000 10000000 10110011 01010000 00000000 00000001 00000000 00000000 01000000 01001010 11111111
 
The data is big-endian (network order), you can reverse the bytes to get right converted value in little-endian system. Example:
C#:
Array.Reverse(bytes);
return BitConverter.ToInt32(bytes, 0);
 
I will try tomorrow. I imagine it will be right.
I have a question, I cant see it at the moment.
What is the mechanism that makes sure the right bytes are read and keeps the current position of the file?
Thanks,
 
I have a question, I cant see it at the moment.
What is the mechanism that makes sure the right bytes are read and keeps the current position of the file?
A FileStream has an internal pointer that indicates the current position. You can get and set it via the Position property and set it via the Seek method. The Read method reads bytes from the current position and advances it by the number of bytes read. For instance, this:
C#:
stream.Read(bytes, 0, 4);
reads (a maximum of) 4 bytes from the current stream position, advances the position by the number of bytes read and stores those bytes in the array provided, starting at index 0.
 
Hi, how do I get the below to work.
I think ToSingle is to floating point.
Thanks,

C#:
int ReadFloat(Stream stream)
            {
                var bytes = new byte[4];

                stream.Read(bytes, 0, 4);

                Array.Reverse(bytes);

                return BitConverter.ToSingle(bytes, 0);

            }
 
What problem are you running into with it?

Right off the bat, I'd you are reading a float, why are you returning an integer?
 
Back
Top Bottom