c++存取dat数据

      众所周知,dat是一个类似加密的二进制格式文件,很多人喜欢将游戏数据保存在dat文件中,只有知道你的存放格式,才能够将数据破解出来,因而研究了dat文件的存取方式。其实就是c++文件的操作,只不过是在取的时候需要按照自己存放的格式获取出来。

本文将实现将结构体数据保存到dat文件,并且将dat文件读取回来。

1.struct结构体的格式数据
      首先定义一个结构体,用以存放存入dat文件的数据,同时,再取的时候按照结构体的格式进行获取操作:
 

#pragma once
#ifndef _STRUCT_H_
#define _STRUCT_H_
 
#include<vector>
#include <iostream>
#include <string>
using namespace std;;
#define MaxSize 10
//设置结构体的边界对齐为1个字节,对于结构体中的char数组,如果不满4的倍数字节,会默认补齐,声明之后数据在内存中是连续存储的。
#pragma pack(1) 
typedef struct _TEST_DAT
{
	int type;
	char name[MaxSize];
	int age;
}TESTDAT;
 
#pragma pack()
 
#endif 

这时的结构体内存结构是对齐的。

2.TxtToFile存取dat文件

         先说存,首先初始化一个结构体,其次将该结构体数据依次保存到指定名字的dat文件中,如下:

TxtToFile.h:

#pragma once
#ifndef _TXT_TO_FILE_H_
#define _TXT_TO_FILE_H_
#include<vector>
#include <iostream>
#include <fstream>
#include <string>
#include "Struct.h"
#include <stdio.h>
using namespace std;
class TxtToFile
{
public:
	TxtToFile();
	~TxtToFile();
	//外调函数,保存到dat文件
	bool  SaveToDat(string _datPath);
private:
	TESTDAT	m_dat;
	fstream	m_datstream;
	vector<TESTDAT>	m_getdat;
 
private:
	// 把基本的Number类型写入文件流中
	template<class T>
	bool Write(T value)
	{
		//re
		m_datstream.write(reinterpret_cast<char *>(&value), sizeof(T));
		return true;
	}
	//把字符串写入文件流
	void  WriteString(string _str, int	_count);
};
#endif

TxtToFile.cpp :

#include "stdafx.h"
#include "TxtToFile.h"
#include <sstream>
 
TxtToFile::TxtToFile()
{
	m_dat = TESTDAT{
		0,
		"dasdasd",
		1
	};
	
}
 
 
TxtToFile::~TxtToFile()
{
}
bool TxtToFile::SaveToDat(string _datPath)
{
	if (_datPath.size() == 0)
	{
		return false;
	}
	m_datstream.open(_datPath, fstream::out | fstream::binary);//以二进制的形式打开文件
	if (!m_datstream.is_open())
	{
		cout << "open" << _datPath << "Failed" << endl;
		m_datstream.close();
		return false;
	}
	Write(m_dat.type);//存入数据
	WriteString(m_dat.name, MaxSize);
	Write(m_dat.age);
	//Write(m_dat);
	cout << "Successed" << endl;
	m_datstream.close();
	return true;
}
void TxtToFile::WriteString(string _str, int _count)
{
	if (_str.length()>=_count)
	{
		cout << "write string error!" << endl;
		return;
	}
	m_datstream << _str;
	int len = _count - _str.length();
	while (len--)
	{
		m_datstream << '\0';
	}
}

        这个时候,已经把数据存入到dat文件中,接下来就是取数据了,如下:

首先在头文件中加两个函数:

	//从dat文件读取数据
	bool GetFromDat(string _datPath);
	__int64 getFileSize(const char *filename);

cpp:

bool TxtToFile::GetFromDat(string _datPath)
{
	if (_datPath.size()==0)
	{
		return false;
	}
	
	__int64 scount = 0;
	__int64 stuctsize = sizeof(TESTDAT);
	TESTDAT testdat;
	__int64 filesize = getFileSize(_datPath.c_str());
	if (filesize==0|| filesize<stuctsize ||(filesize%stuctsize)!=0)
	{
		return false;
	}
	scount = filesize / stuctsize;
 
	FILE *inStream = NULL;
	const char* name = _datPath.c_str();
	inStream = fopen(name, "rb");
	if (inStream == NULL) return false;
	for (int i = 0; i < scount; i++)
	{
		//size_t fread(void *ptr, size_t size, size_t n, FILE *stream);
		//参数ptr是保存读取的数据,void*的指针可用任何类型的指针来替换,如char*、int *等等来替换;
		//size是每块的字节数;n是读取的块数,如果成功,返回实际读取的块数(不是字节数),本函数一般用于二进制模式打开的文件中。
		fread(&testdat, stuctsize, 1, inStream);
		/*if (testdat.duration < 0)
		{
			fclose(inStream);
			return false;
		}*/
		m_getdat.push_back(testdat);
	}
 
	fclose(inStream);
 
	return true;
}
 
__int64 TxtToFile::getFileSize(const char *filename)
{
	__int64 size = 0;
	/*FILE *fp = fopen(filename, "rb");
	if (!fp)
	{
		return 0;
	}
	fseek(fp, 0, SEEK_END);
	size = ftell(fp);
	fseek(fp, 0, SEEK_SET);
	fclose(fp);*/
	fstream instreams;
	instreams.open(filename, ios::_Nocreate);
	if (!instreams.is_open())
	{
		return 0;
	}
	instreams.seekg(0, ios::end);
	size = instreams.tellg();
	instreams.close();
	return size;
}

读的时候用的是C语言的,因为映射一下就是结构体了,而且存的时候没有存空格\n\t之类的分隔符,所以用getline不好取。

3.测试样例

main函数:

// DatTxt.cpp : 定义控制台应用程序的入口点。
//
 
#include "stdafx.h"
#include "TxtToFile.h"
 
int _tmain(int argc, _TCHAR* argv[])
{
	TxtToFile ttofile;
	ttofile.SaveToDat("Test.Dat");
	ttofile.GetFromDat("Test.Dat");
	return 0;
}

运行视图:

 

成功,并且能在目录下找到dat文件,如果要看取出来的数据,那么需要加断点查看咯

Over

猜你喜欢

转载自blog.csdn.net/ok060/article/details/132510781
今日推荐