2017-04-11 65 views
1

大家好,如何在结构中存储二进制文件数据?

我有一个如下所示的文件(Material.dat),它是二进制文件,我想从文件中读取数据并将其放入结构中,以便使用GetRecord()函数。

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)); 

我的疑问是什么作为记录号传递给Get Record()函数? (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; 
} 
+0

您必须跟踪您已阅读的条目数量。可能二进制文件中的每个条目都具有相同的大小(如果不是,那么这个函数将不起作用,因为它假定每个元素的大小相同),所以提供'RecordNumber'允许偏移计算在哪里查找这个特定条目。 – Rogus

+0

谷歌protobuf可能是你的解决方案。 – sailfish009

+0

是的,二进制文件中的每个条目具有相同的大小。如何跟踪条目数量以及如何计算偏移量?你能否让我清楚明白。 –

回答

0

我会用这种类型的接口:

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 
} 

无论读/写是二进制的,依赖于实现。阅读和写作总是连续进行。读取特定记录可能是可能的,在这种情况下,必须在读取记录之前完成流指针操作。我添加了在一个特定位置(不管是读取还是写入)寻找流的可能性,使用Record接口来读/写。

0

首先要回答这个问题,你问的方式:要阅读所有的数据到一个载体,我建议更改代码的假设,第一个记录有RecordNumber = 0:

LONG lOffset = RecordNumber * RecordSize; 

然后,读取所有记录到一个std :: vector的,你可以不喜欢

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); 
} 

现在考虑您阅读所有的记录顺序,实际上你可以忘掉RecordNumber和调用SetFilePointer,因为文件读取位置应该由ReadFile调用更新。在任何情况下,为了使代码具有更好的可移植性,最好使用C++标准库中的文件IO函数,而不是MS Windows特定的调用(如WernerErasmus提出的,详情参见here)。

相关问题