Revanth Rao
Revanth Rao

Reputation: 39

How to store binary file data in structure?

Hi all,

I have a file shown below(Material.dat) which is binary file , I want to read data from the file and put in the structure for that I have used GetRecord() function.

HANDLE hFileMac = ::CreateFile(_T("Material.dat"), GENERIC_READ, FILE_SHARE_READ, NULL,
  OPEN_EXISTING, FALSE ? FILE_FLAG_SEQUENTIAL_SCAN : FILE_ATTRIBUTE_NORMAL, NULL);

 if (!(hFileMac != INVALID_HANDLE_VALUE))
 {
  return;
 }

 GetRecord(hFileMac, RECORD_NUMBER, sizeof(Header), reinterpret_cast<void *>(&Header));

My doubt is what to pass as a record number to Get Record() function?

GetRecord(hFileMac, RECORD_NUMBER, sizeof(Header), reinterpret_cast(&Header));

int GetRecord(HANDLE hFile, int RecordNumber, int RecordSize, void *RecordPtr)
{
 if (RecordNumber <= 0 || RecordSize <= 0)
  return 1;
 LONG lOffset = (RecordNumber - 1) * RecordSize;

 if (SetFilePointer(hFile, lOffset, NULL, FILE_BEGIN) == 0xFFFFFFFF)
  return 2;

 DWORD dwSize;

 if (::ReadFile(hFile, RecordPtr, RecordSize, &dwSize, NULL) == 0)
  return 3;

 return 0;
}

Upvotes: 1

Views: 170

Answers (2)

Gert Wollny
Gert Wollny

Reputation: 529

First to answer the question the way you asked it: To read all the data into a vector I would suggest to change the code to assume that the first record has a RecordNumber=0:

LONG lOffset = RecordNumber * RecordSize;

Then, to read all records into a std::vector you could do something like

struct Record {...}; 
typedef Record* RecordPtr; 
...
std::vector<Record> data_records; 
Record current; 

while (GetRecord(hFile, data_records.size(), sizeof(Record), &current) == 0 ) {
    data_records.push_back(current); 
}

Now considering that you read all the records sequentially, you can actually forget about the RecordNumberand the call to SetFilePointer, because the file read position should be updated by the ReadFile call.

In any case, for better portability of the code it would be better to use file IO functions from the C++ standard library instead of the MS Windows specific calls (like proposed by WernerErasmus, for details see here).

Upvotes: 0

Werner Erasmus
Werner Erasmus

Reputation: 4076

I would use this type of interface:

class Record {
  //Reads a single record from "from", incrementing the associated 
  // read pointer, and returning eof or bad, depending on whether record
  // state is consistent, and whether eof stream is reached
  std::istream& read(std::istream& from);
  //Writes a single record to "to"
  std::ostream& write(std::ostream& to);
}

struct MaterialStore {
  //Reads all records from "from", in sequence, using Record interface
  std::istream& read(std::istream& from);

  //Writes all records in "to" to, in sequence, using Record interface
  std::ostream& write(std::ostream& to);

  //Perhaps to perform that seeking for a specific record, the
  // Use Record interface for retrieval.
  std::iostream& seekRecord(std::iostream& stream, int index pos);

  const Record& getRecords(); //Returns all the records read
}

Whether read/write is binary, depends on the implementation. Reading and writing is always done consecutively. It may be possible to read a specific record, in which case stream pointer manipulation must be done prior to reading the record. I've added the possibility of seeking in a stream for a specific location (be it read or write), the use the Record interface to read/write.

Upvotes: 0

Related Questions