您的位置:首页 > 编程语言 > C语言/C++

C语言二进制文件读取解析

2015-01-25 23:59 253 查看
// FileDefine.h

#ifndef _FILEDEFINE_H_

#define _FILEDEFINE_H_

#include <string>

using namespace std;

/*

文件操作,对磁盘的读写:

fopen 打开模式 和 缓存区大小

打开模式:

r:read 读没有文件会读取失败

w:write 写会清空文件,没有可以创建文件

a:append 写追加没有文件可以创建文件

+: input + output

b: binary 没有b修饰的是默认ascii文本操作

t: text,是文本文件方式打开读写,如果没有b修饰,那么默认就是t 文本方式。

wb:只写方式打开二进制文件,可以写入的时候去掉文本结束符。

fwrite返回的长度不等于要写的长度,那说明磁盘满了。

fclose

读写:

字符读写:

fputc fgetc

字符串读写:

fputs fgets

数据块读写:

fread 连续读写,文件内部的指针游标会跟随累加

fwrite 连续写也会累加

参数:new内存,结构体的地址。

格式化读写:

fscanf(fp,"%d%s", num, name)格式化读取,将从文件指针fp中读取的数据存入num,name中,然后格式化输出

fprintf

跳转计算访问索引:

fseek跳到指定的位置

ftell返回当前的长度

EOF是-1作为文本文件结束的标志,但是在二进制文件中不行,需要用到feof函数。

屏幕操作,对键盘和屏幕的读写:

printf输出到屏幕

gets从屏幕输入

getc

putchar显示读取的字符

*/

// 包头

struct PackageHeader

{

int m_nCount; // 文件的个数

int m_nLen; // 文件的长度

PackageHeader()

{

m_nCount = 0;

m_nLen = 0;

}

/*PackageHeader& operator =(const PackageHeader &b)

{

this->m_nCount = b.m_nCount;

this->m_nLen = b.m_nLen;

return (*this);

}*/

};

// 每个文件的索引信息

struct FileList

{

unsigned int m_nFileID;

int m_nOffset; // 每个文件在包中的偏移

int m_nSize; // 文件的大小

FileList()

{

m_nFileID = 0;

m_nOffset = 0;

m_nSize = 0;

}

};

// 数据内容

struct StudentData

{

unsigned int m_nNum; // 序号

unsigned int m_nLevel; // 等级

unsigned int m_nScroe; // 分数

string m_szName;

//string m_strName; // 名字

//string m_strDepartment; // 部门

//string m_strSchool; // 学校

};

#endif

// FilePackage.h

#ifndef _FILEPACKAGE_H_

#define _FILEPACKAGE_H_

#include <stdio.h>

#include <map>

#include <vector>

using namespace std;

#include "FileDefine.h"

class CFilePackage

{

public:

CFilePackage();

~CFilePackage(){};

void OpenFile(const string strFilePath, char *szMode);

void ReadFile();

void WriteFile(vector<StudentData> *pVecData);

StudentData* GetFileData(unsigned int fileID);

void CloseFile();



private:

FILE *m_pFile;

PackageHeader m_fileHead;

map<unsigned int, FileList> m_mapFileList; // unsigned int是文件FileID



StudentData m_stuData; // 数据

};

#endif

// FilePackage.cpp

#include "stdafx.h"

#include "FilePackage.h"

CFilePackage::CFilePackage()

{

m_pFile = NULL;

//PackageHeader m_fileHead;

//map<unsigned int, FileList> m_mapFileList; // unsigned int是文件FileID

//StudentData m_stuData; // 数据

}

void CFilePackage::OpenFile(const string strFilePath, char *szMode)

{

if(strFilePath.empty())

{

return;

}

m_pFile = fopen(strFilePath.c_str(), szMode);

if(m_pFile == NULL)

{

return;

}

}

void CFilePackage::CloseFile()

{

fclose(m_pFile);

m_pFile = NULL;

}

void CFilePackage::ReadFile()

{

if(m_pFile == NULL)

{

return;

}

// 直接读取头文件到内存结构体中

fread(&m_fileHead, sizeof(PackageHeader),1, m_pFile);

m_mapFileList.clear();

// 读取m_nCount个文件的索引

for(int i = 0; i < m_fileHead.m_nCount; i++)

{

FileList fileListTemp;

// 直接读取到索引结构体中

fread(&fileListTemp, sizeof(FileList), 1, m_pFile);

// 连续的读取,保存索引

m_mapFileList[fileListTemp.m_nFileID] = fileListTemp;

}

}

StudentData* CFilePackage::GetFileData(unsigned int fileID)

{

map<unsigned int, FileList>::iterator itFile = m_mapFileList.find(fileID);

if(itFile == m_mapFileList.end())

{

return NULL;

}

FileList *fileList = &(itFile->second);

// 直接跳转,读取文件数据

fseek(m_pFile, fileList->m_nOffset, SEEK_SET);

fread(&m_stuData, sizeof(StudentData), 1, m_pFile);

//int nCurLength = ftell(m_pFile);//ftell函数是用来获取文件的当前读写位置;

// 重置文件指针到文件头部

fseek(m_pFile, 0, SEEK_SET); // fseek(fp,OL,SEEK_END);移动到文件结尾

return &m_stuData;

}

void CFilePackage::WriteFile(vector<StudentData> *pVecData)

{

//typedef struct tagPackageHeader

//{

// int m_nCount; // 文件的个数

// int m_nLen; // 文件的长度

//}PackageHeader;

//// 每个文件的索引信息

//typedef struct tagFileList

//{

// unsigned int m_nFileID;

// int m_nOffset; // 每个文件在包中的偏移

// int m_nSize; // 文件的大小

//}FileList;

if(m_pFile == NULL && pVecData == NULL)

{

return;

}

int nCount = (int)pVecData->size();

fseek(m_pFile, 0, SEEK_SET);

fwrite(&m_fileHead, sizeof(PackageHeader), 1, m_pFile);

FileList fileList;

fwrite(&fileList, sizeof(FileList), nCount, m_pFile);

map<unsigned int, FileList> tempFileList;



for(int i = 0; i < nCount; i++)

{

StudentData stuData;

FileList fileList;

fileList.m_nFileID = (*pVecData)[i].m_nNum;

fileList.m_nOffset = ftell(m_pFile);

fileList.m_nSize = 3 * sizeof(unsigned int) + (*pVecData)[i].m_szName.length();

tempFileList[stuData.m_nNum] = fileList;



stuData.m_nNum = (*pVecData)[i].m_nNum;

stuData.m_nLevel = (*pVecData)[i].m_nLevel;

stuData.m_nScroe = (*pVecData)[i].m_nScroe;

stuData.m_szName = (*pVecData)[i].m_szName;

fwrite(&stuData, sizeof(StudentData), 1, m_pFile);

}

map<unsigned int, FileList>::iterator itrFileList = tempFileList.begin();

fseek(m_pFile, sizeof(PackageHeader), SEEK_SET);

for(; itrFileList != tempFileList.end(); ++itrFileList)

{

fwrite(&(itrFileList->second), sizeof(FileList),1, m_pFile);

}



fseek(m_pFile, 0, SEEK_END);

int nFileLen = ftell(m_pFile);

m_fileHead.m_nCount = (int)tempFileList.size();

m_fileHead.m_nLen = nFileLen;

fseek(m_pFile, 0, SEEK_SET);

fwrite(&m_fileHead, sizeof(PackageHeader), 1, m_pFile);

fseek(m_pFile, 0, SEEK_SET);

tempFileList.clear();

}

//// FileOperate.cpp : Defines the entry point for the console application.

//

#include "stdafx.h"

#include <iostream>

using namespace std;

#include "FilePackage.h"

int _tmain(int argc, _TCHAR* argv[])

{

CFilePackage File;

File.OpenFile("d:\\jiayuan.bin", "wb");

vector<StudentData> vecData;

StudentData data;

data.m_nNum = 100;

data.m_nLevel = 9;

data.m_nScroe = 78;

data.m_szName = "家园";

vecData.push_back(data);

data.m_nNum = 101;

data.m_nLevel = 8;

data.m_nScroe = 88;

data.m_szName = "欧圈圈";



vecData.push_back(data);

File.WriteFile(&vecData);

File.CloseFile();

File.OpenFile("d:\\jiayuan.bin", "rb");

File.ReadFile();

StudentData *pResData;

while(1)

{

cout<< "请输入人物ID号:"<<endl;

int nNum;

cin>> nNum;

pResData = File.GetFileData(nNum);

if(pResData != NULL)

{

cout<<"查询结果:"<<endl;

cout<<"序号:"<<pResData->m_nNum<<" 名字:"<<pResData->m_szName<<" 等级:"<<pResData->m_nLevel<<" 分数:"<<pResData->m_nScroe<<endl;

}

else

{

cout<<"序号没有查询结果!"<<endl;

}



}



return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: