// 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 文本方式。
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;
}