Search code examples
firemonkeyc++builderc++builder-10.3-rio

Reading binary data


I am trying to read data from a binary file. One block of data is 76 bytes long (this varies with the number of the 2-byte "main data items" in the middle of the block). The first datum is 4 bytes, second is 4 bytes, and then there are a bunch of 2 byte main data items, and at the end are 2 more 2-byte pieces of data.

enter image description here

Based on this Delphi sample I've learned how to read the file with the code below:

short AShortInt; // 16 bits
int AInteger; // 32 bits
try
{
 infile=new TFileStream(myfile,fmOpenRead); // myfile is binary
 BR = new TBinaryReader(infile, TEncoding::Unicode, false);
 for (int rows = 0; rows < 5; rows++) {  // just read the first 5 blocks of data for testing
  AInteger = BR->ReadInt32(); // read first two 4 byte integers for this block
  AInteger = BR->ReadInt32();
  for (int i = 0; i < 32; i++) { // now read the 32 2-byte integers from this block
   AShortInt = BR->ReadInt16();
  }
  AShortInt = BR->ReadInt16(); // read next to last 2-byte int
  AShortInt = BR->ReadInt16(); // read the last 2-byte int
}
delete infile;
delete BR;
Close();
}
catch(...)
{
 delete infile;  // closes the file, doesn't delete it.
 delete BR;
 ShowMessage("Can't open file!");
 Close();
}

But, what i would like to do is use a 76-byte wide buffer to read the entire block, and then pick the various datum out of that buffer. I put together the following code based on this question and i can read a whole block of data into the buffer.

UnicodeString myfile = System::Ioutils::TPath::Combine(System::Ioutils::TPath::GetDocumentsPath(), "binaryCOM.dat");
TFileStream*infile=0;
try
{
 infile=new TFileStream(myfile,fmOpenRead);
 const int bufsize=76;
 char*buf=new char[bufsize];
 int a = 0;
 while(int bytesread=infile->Read(buf,bufsize)) {
   a++; // just a place to break on Run to Cursor
 }
 delete[]buf;
}
catch(...)
{
  delete infile;  
  ShowMessage("Can't open file!");
  Close();
}

But i can't figure out how to piece together subsets out of the bytes in the buffer. Is there a way to concatenate bytes? So i could read a block of data into a 76 byte buffer and then do something like this below?

unsigned int FirstDatum = buf[0]+buf[1]+buf[2]+buf[3];  // concatenate the 4 bytes for the first piece of data

This will be an FMX app for Win32, iOS, and Android built in C++Builder 10.3.2.


Solution

  • Here is my modified code using Remy's suggestion of TMemoryStream.

    UnicodeString myfile = System::Ioutils::TPath::Combine(System::Ioutils::TPath::GetDocumentsPath(), "binaryCOM.dat");
    
    TMemoryStream *MS=0;
    TBinaryReader *BR=0;
    std::vector<short> myArray;
    short AShortInt;
    int AInteger;
    int NumDatums = 32; // the variable number of 2-byte main datums
    
    try
    {
      MS = new TMemoryStream();
      MS->LoadFromFile(myfile);
      BR = new TBinaryReader(MS, TEncoding::Unicode, false);
      for (int rows = 0; rows < 5; rows++) {  // testing with first 5 blocks of data
        AInteger = BR->ReadInt32(); // read first two 4 byte integers
        AInteger = BR->ReadInt32(); // here
        for (int i = 0; i < NumDatums; i++) {  // read the main 2-byte data
          AShortInt = BR->ReadInt16();
          myArray.push_back(AShortInt); // push it into vector
        }
        AShortInt = BR->ReadInt16(); // read next to last 2-byte int
        AShortInt = BR->ReadInt16(); // read the last 2-byte int
        // code here to do something with this block of data just read from file
      }
    }
    delete MS;
    delete BR;
    }
    catch(...)
    {
     delete MS;  
     delete BR;
     ShowMessage("Can't open file.");
    }