0

I'm trying to use binaryreader to 'pull apart' and index a binary file but I need some help. I got this so far:

using (BinaryReader b = new BinaryReader(File.Open(openRaw.FileName, FileMode.Open)))
                {
                    int pos = 0;
                    // 2A.
                    // Use BaseStream.
                    int length = (int)b.BaseStream.Length;
                    while (pos < length)
                    {


                        //Move on
                        pos += sizeof(int);
                    }
                }

But now the hard part starts, atleast for me.

The file contains byte arrays consisting of 169 bytes seperated by a ! (0x21) character. For each byte array I need to split it into multiple values consisting of 16 and 8 bits. I know the index exactly and it is always the same. E.g.: Index 0+1 contains a U16 decimal value being speed, index 16+17 contains a S16 decimal value being pressure. And so on through each array of 169 bytes.

How should I handle this?

EDIT:

I no have this:

FileInfo f = new FileInfo(openRaw.FileName);
                double s1 = Convert.ToDouble(f.Length);
                double s2 = s1 / 170;
                double s3 = Math.Floor(s2);
                double s4 = s3 * 170;

                using (BinaryReader b = new BinaryReader(File.Open(openRaw.FileName, FileMode.Open), Encoding.ASCII))
                {
                    int pos = 0;
                    // 2A.
                    // Use BaseStream.

                    while (pos < s4)
                    {

                         while (b.PeekChar() != -1)
                        {

                            if (b.ReadByte() != 0x21)
                            {
                                flag = 1;
                            }                                

                            temp = b.ReadBytes(2);
                            Array.Reverse(temp);
                            seconds = BitConverter.ToUInt16(temp, 0);
                            temp = b.ReadBytes(2);
                            Array.Reverse(temp);
                            PW1 = BitConverter.ToUInt16(temp, 0);
                            temp = b.ReadBytes(2);
                            Array.Reverse(temp);
                            PW2 = BitConverter.ToUInt16(temp, 0);
                            temp = b.ReadBytes(2);
                            Array.Reverse(temp);
                            RPM = BitConverter.ToUInt16(temp, 0);
                            temp = b.ReadBytes(2);
                            Array.Reverse(temp);
                            advance = BitConverter.ToInt16(temp, 0);
                            NN = b.ReadBytes(6);
                            temp = b.ReadBytes(2);
                            Array.Reverse(temp);
                            Baro = BitConverter.ToInt16(temp, 0);
                            temp = b.ReadBytes(2);
                            Array.Reverse(temp);
                            map = BitConverter.ToInt16(temp, 0);
                            temp = b.ReadBytes(2);
                            Array.Reverse(temp);
                            mat = BitConverter.ToInt16(temp, 0);
                            temp = b.ReadBytes(2);
                            Array.Reverse(temp);
                            clt = BitConverter.ToInt16(temp, 0);
                            temp = b.ReadBytes(2);
                            Array.Reverse(temp);
                            tps = BitConverter.ToInt16(temp, 0);
                            temp = b.ReadBytes(2);
                            Array.Reverse(temp);
                            bat = BitConverter.ToInt16(temp, 0);
                            temp = b.ReadBytes(2);
                            Array.Reverse(temp);
                            AFR = BitConverter.ToInt16(temp, 0);
                            stemp16 = b.ReadInt16();
                            temp = b.ReadBytes(2);
                            Array.Reverse(temp);
                            knock = BitConverter.ToInt16(temp, 0); ;  //33
                            NN = b.ReadBytes(135);

                            table1.Rows.Add((seconds * 0.00390625), RPM, map, (tps * 0.1), ((mat - 320) * 0.05555), ((clt - 320) * 0.05555), (PW1 * 0.000666), (PW2 * 0.000666), (advance * 0.1), (knock * 0.1), (RPM/100), (Baro * 0.1), (AFR * 0.1), (bat * 0.1));

                        }

                        //Move on
                        pos = pos+= sizeof(int);
                    }
                    dataGridView1.DataSource = table1;
                }
Felix
  • 89
  • 1
  • 12

1 Answers1

1

Just read the values from the reader in the order they come in the file. Example:

ushort speed = b.ReadUInt16();
byte something = b.ReadByte();
sbyte someOther = b.ReadSByte();
short pressure = b.ReadInt16();

There are BinaryReader methods for reading most data types.

Example of looping the stream:

while (b.PeekChar() != -1) {
  if (b.ReadByte() != 0x21) {
    // error - didn't find valid separator
  }
  ushort speed = b.ReadUInt16();
  // and read another 167 bytes of data
}
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • OK! I wasn't aware that it was so simple. Before I do that I need to isolate the byte array between each ! character. How to do that in/with binaryreader? – Felix Jun 27 '13 at 08:27
  • @Felix: Why do you think that you need to do that? You can do that, but then you will have a byte array that you have to extract the values from. Just read your 169 bytes and then read the byte that is the separator character, and repeat until the end of the file. – Guffa Jun 27 '13 at 08:38
  • Hmm, so I have to create a loop which reinitiates the reading every time a seperator is reached? Or have it count bytes? – Felix Jun 27 '13 at 08:43
  • @Felix: You should keep track of how many bytes you read from the file so that you read 169 bytes in each iteration, then the separator. You can't look for every 0x21 value in the file, as that may also occur among the 169 bytes of data. If for example the speed is 289, that would be represented as the two bytes 0x21 0x01. – Guffa Jun 27 '13 at 08:49
  • I understand what you mean. I'm not enterily sure how such a loop should look. Also the file always begins with a seperator. Could you give me an example? – Felix Jun 27 '13 at 08:59
  • @Felix: I added an example above. – Guffa Jun 27 '13 at 10:24
  • Thanks Guffa! Much appriciated! One final thing. If lets say I read byte 0 and 1, I don't need byte 2 through 4, and want to continue with byte 5? How can I skip those during the iteration? – Felix Jun 27 '13 at 10:28
  • @Felix_ You can use the `ReadBytes` method to read a specific number of bytes, and just ignore the result. – Guffa Jun 27 '13 at 10:34
  • See my original post for the code I'm tried just now. Its not (yet) working correctly.The values in the DataTable are incorrect. Also it seems that the error (not finding 0x21) is called alot. – Felix Jun 27 '13 at 11:35
  • Its reading the bytes in reverse! E.g. 01 FF the program reads it as FF 01?? – Felix Jun 27 '13 at 11:52
  • @Felix: The BinaryReader reads data in little-endian format. If you have a file in big-endian format, you have to do a little more work to read the data. For example reading an unsigned short as `b.ReadByte() * 256 + b.ReadByte()`. – Guffa Jun 27 '13 at 12:20
  • I came to same conclusion after some research. I applied `temp = b.ReadBytes(2);` and `Array.Reverse(temp);` in combination with `RPM = BitConverter.ToUInt16(temp, 0);`.. It seems to function. Is that also a good way? – Felix Jun 27 '13 at 12:39
  • @Felix: Yes, that works fine. It's not the most efficient way, but normally that is not a problem. – Guffa Jun 27 '13 at 12:46
  • I've implemented it for every value (see above), but only the first row of values seems to be correct.. We're almost there tho! Something not quite right as for the loop still? – Felix Jun 27 '13 at 13:14
  • Yep you we're right! Its working now. Only thing I noticed is, that sometimes a datapackage isn't complete, the processing device could have been cut from power in the middle of a data package. Thats why... Is there any way to compensate for such event in the loop? If a package isn't complete it may be disregarded. – Felix Jun 28 '13 at 15:04
  • @Felix: Check the file size before you start, so that you can calculate how many complete packeges there are. – Guffa Jun 28 '13 at 15:24
  • Thats a possibility! But what if there is a imcomplete package in the middle of the file? Maybe checking at the begin of the iteration if the next 169 bytes are available/present before processing? Not sure how to implement that tho. I could always change the '!' seperator into something else if that would be helpful. – Felix Jun 28 '13 at 19:37
  • @Felix: By checking the length of the file you know how many complete packeges there can be. There are no holes in the middle of the file, so looking for the next separator is the only way to find out if there is an incomplete package in the middle of the file. If that happens you can look for the next separator, but you won't ever be completely certain that you actually found a separator. There is even a small risk (1:256) that there is a corrupted package even if you find a separator at the right place. – Guffa Jun 28 '13 at 20:16
  • @Yep I got your point. Thnx for explanation! I will try to find a solution. I think I will make the device that is writing the file start with a new file each run instead of keep writing in the same file which can cause corrupted packages end up in the middle of the file. I do have to check for the number of complete packages to get rid of the possible corrupt package at the end. – Felix Jun 28 '13 at 20:24