衆所周知,dat是一個類似加密的二進制格式文件,很多人喜歡將遊戲數據保存在dat文件中,只有知道你的存放格式,才能夠將數據破解出來,因而研究了dat文件的存取方式。其實就是c++文件的操作,只不過是在取的時候需要按照自己存放的格式獲取出來。
本文將實現將結構體數據保存到dat文件,並且將dat文件讀取回來。
1.struct結構體的格式數據
首先定義一個結構體,用以存放存入dat文件的數據,同時,再取的時候按照結構體的格式進行獲取操作:
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
#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;
}
運行視圖: