应用:
其中 _KeyBinaryFile类是创建一种新的文件格式,上次已介绍,但用的是C#。
代码
_Object.h
/*******************************************************************************************
文件名 : Object.h
功能 : object 类
作者 : 李锋
手机 : 13828778863
Email : ruizhilf@139.com
创建时间 : 2022年11月01日
最后一次修改时间 : -------------------------------------------------2023年03月27日
(1) 如果类定义中有指针或引用变量或对象,为了避免潜在错误,最好重载拷贝构造函数和赋值函数。
(2) 如果使你的类能够给其它可以排序功能的类使用,就必须重载 < > == 运算符
*********************************************************************************************/
#ifndef __OBJECT_H_
#define __OBJECT_H_
#include "_Macro.h"
_LF_BEGIN_
//#define _OBJECT_DEBUG_
//-----------------------------------------------------前置声明
class _ByteArray;
class _StrW;
class _StrA;
/// <summary>
/// 不命名 _Object ,是因为跟 System::Object 同名
/// </summary>
class _Object
{
private:
/// <summary>
/// _Object 对象计数器
/// </summary>
static __int64 _iObjectCount;
/// <summary>
/// 是否进行全局初始化
/// </summary>
static bool _bInitializeGlobal;
protected:
//inline virtual void InitData(const int& nBuffer, const int& nDefaultBuffer = 15) {};
//inline virtual void InitData() {};
public://----------------------------------------------构造析构
_Object();
virtual ~_Object();
public://----------------------------------------------重写接口
/// <summary>
/// 清空数据
/// </summary>
/// 创建时间:2022-11-13 最后一次修改时间:2022-11-13
inline virtual void ClearData() {};
/// <summary>
/// 清空内存,重置为实始化状态
/// </summary>
inline virtual void ClearMemory() {};
virtual _string ToString() const;
/// <summary>
/// 把对象保存在内存中。
/// </summary>
/// <returns></returns>
/// 创建时间:2022-11-13 最后一次修改时间:2023-03-12
inline virtual _ByteArray& PackageMemory(_ByteArray& baPackageMem) const;
/// <summary>
/// 从内存中读出对象
/// </summary>
/// <param name="pPackageMem">指向数据的指针</param>
/// <param name="nStart">开始读出的位置</param>
/// 创建时间:2022-11-13 最后一次修改时间:2023-03-12
inline virtual void SplitFromMemory(const _byte* pPackageMem, const _uint nStart = 0);
/// <summary>
/// 如果大于 oRight 则返回1,等于返回0,小于返回-1
/// </summary>
/// <param name="oRight"></param>
/// <returns></returns>
/// 创建时间:2022-11-13 最后一次修改时间:2022-11-13
virtual int CompareTo(const _Object& oRight)const;
/// <summary>
/// 释放本身内存,托管新的内存。
/// </summary>
/// <param name="pData"></param>
/// <param name="nDataMemoryLength">数据长度</param>
/// <param name="nMemoryLength">使用内存长度</param>
/// 创建时间:2023-01-04 最后一次修改时间:2023-01-05
virtual void TrusteeshipMem(const _byte* pData, const int nDataMemoryLength, const int& nMemoryLength);
/// <summary>
/// 除非内存给其它对象托管,否则不要调用这个函数。
/// 放置对象当前使用的内存,可能内存已托管给别的对象,
/// 重新初始化当前对象
/// </summary>
/// 创建时间:2023-01-04 最后一次修改时间:2023-01-05
inline virtual void GiveUppMem(){}
/// <summary>
/// 返回对象所使用的内存大小,以Byte计数。
/// </summary>
/// <returns></returns>
/// 创建时间:2023-01-04 最后一次修改时间:2023-01-05
inline virtual int GetMemoryLength() { return 0; }
/// <summary>
/// 返回对象数据所使用的内存大小,以Byte计数。
/// </summary>
/// <returns></returns>
/// 创建时间:2023-01-04 最后一次修改时间:2023-01-05
inline virtual int GetDataMemoryLength() { return 0; }
public:
//-----------------------------------------------------------------运算符重载
/// <summary>
/// 这个函数的意义在于,每个从继承自 _Object 类,都可以转换成 _string
/// </summary>
/// 创建时间:2022-11-13 最后一次修改时间:2022-11-13
operator _string();
inline friend bool operator > (const _Object& oLeft, const _Object& oRight) { return oLeft.CompareTo(oRight) == 1; }
inline friend bool operator < (const _Object& oLeft, const _Object& oRight) { return oLeft.CompareTo(oRight) == -1; }
inline friend bool operator == (const _Object& oLeft, const _Object& oRight) { return oLeft.CompareTo(oRight) == 0; }
public:
/// <summary>
/// 从文件中读取数据
/// </summary>
/// 创建时间:2023-03-14 最后一次修改时间:2023-03-14
void ReadDataFromFile(const _string& sFullPathName);
/// <summary>
/// 把数据保存在文件中
/// </summary>
/// 创建时间:2023-03-14 最后一次修改时间:2023-03-14
void SaveDataToFile(const _string& sFullPathName);
/// <summary>
/// 获取一个文件名
/// </summary>
/// 创建时间:2023-03-14 最后一次修改时间:2023-03-14
_string GetFilePathName()const;
public://----------------------------------------------------------------属性
inline static __int64 GetObjectCount() { return _iObjectCount; }
__declspec(property(get = GetObjectCount)) __int64 ObjectCount;
_string GetTypeName() const;
/// <summary>
///
/// </summary>
__declspec(property(get = GetTypeName)) const _string ClassName;
};
_LF_END_
#endif
_File.h(包含 _BinaryReader _BinaryWriter)
/*******************************************************************************************
文件名 : _File.h
功能 : 文件操作
作者 : 李锋
手机 : 13828778863
Email : ruizhilf@139.com
创建时间 : 2022年11月12日
上一次修改时间 : -------------------------------------------------2022年11月12日
最后一次修改时间 : -------------------------------------------------2022年11月12日
*********************************************************************************************/
#ifndef __FILE_H_
#define __FILE_H_
#include "_Object.h"
#include "_Debug.h"
_LF_BEGIN_
enum _FileMode
{
/// <summary>
/// r 打开以进行读取。如果该文件不存在,或无法找到,fopen_s调用失败。
/// </summary>
Read,
/// <summary>
/// w 打开一个空文件以进行写入。如果该文件存在,其内容将被销毁。
/// </summary>
Write,
/// <summary>
/// a 打开以进行写入 (追加) 而不将新数据写入文件之前删除的 EOF 标记文件的末尾。如果它不存在,则创建该文件。
/// </summary>
Append,
/// <summary>
/// r+ 将打开并读取和写入。 (该文件必须存在。
/// </summary>
ReadWrite,
/// <summary>
///w+ 打开一个空的文件进行读写。如果该文件存在,其内容将被销毁。
/// </summary>
WriteRead,
/// <summary>
/// a+ 将打开并读取文件和追加。追加操作包括删除 EOF 标记的新数据写入到文件并在编写完成后还原 EOF 标记之前。如果它不存在,则创建该文件。
/// </summary>
AppendReadWrite,
};
class _File : public _Object
{
public:
static _string GetErrorText(const int iErrorCode);
};
class _BinaryReader : public _Object
{
/// <summary>
/// 文件指针
/// </summary>
FILE* _pf;
public:
_BinaryReader(const _string& sFullPathName);
~_BinaryReader();
/// <summary>
/// 获取文件长度,注意文件指针会指放到未端。
/// </summary>
/// <returns></returns>
int GetLength();
/// <summary>
/// 获取文件长度,注意文件指针会指放到未端。
/// </summary>
__declspec(property(get = GetLength)) const int Length;
/// <summary>
/// 重置文件指针于开始位置
/// rewind函数作用等同于 (void)fseek(stream, 0L, SEEK_SET);
/// </summary>
void rewind() { ::rewind(_pf); }
_ByteArray ReadAll();
int ReadInt();
_byte ReadByte();
_ByteArray ReadByteArray(int nLength);
/// <summary>
/// 注意: nMemoryLength 是内存长度,不是字符个数。
/// </summary>
/// <param name="nMemoryLength"></param>
/// <returns></returns>
_Str<wchar_t> ReadWString(const int& nMemoryLength);
/// <summary>
/// 注意: nMemoryLength 是内存长度,不是字符个数。
/// </summary>
/// <param name="nMemoryLength"></param>
/// <returns></returns>
_Str<wchar_t> ReadOldWString(const int& nMemoryLength);
};
/// <summary>
///
/// </summary>
/// 创建时间:2022-12-29 最后一次修改时间:2022-12-29
class _BinaryWriter : public _Object
{
private:
/// <summary>
/// 文件指针
/// </summary>
FILE* _pf;
public:
_BinaryWriter(const _string &sFullPathName, const _FileMode &fm = _FileMode::Write);
~_BinaryWriter();
public:
/// <summary>
///
/// </summary>
/// <typeparam name="Type"></typeparam>
/// <param name="pArray"></param>
/// <param name="nCount"></param>
/// <returns></returns>
/// 创建时间:2022-12-29 最后一次修改时间:2022-12-29
template<typename Type>
inline void Write(const Type* pArray, const int nCount)
{
assert(nCount >= 0 && pArray != null);
int nTrueCount = ::fwrite(pArray, sizeof(Type), (size_t)nCount, _pf);
if (nTrueCount != nCount)
{
d.PrintError(_t("inline void Write(const Type* pArray, const int nCount): 写入数据个数有错误!"));
}
}
/*
virtual void Write(array<unsigned char>^ buffer) new;
virtual void Write(array<unsigned char>^ buffer, int index, int count) new;
virtual void Write(array<wchar_t>^ chars) new;
virtual void Write(array<wchar_t>^ chars, int index, int count) new;
virtual void Write(bool value) new;
virtual void Write(double value) new;
virtual void Write(float value) new;
virtual void Write(int value) new;
virtual void Write(long long value) new;
virtual void Write(short value) new;
*/
inline void WriteByte(const _byte &bValue) { Write<_byte>(&bValue, 1); }
/*
virtual void Write(System::Decimal value) new;
virtual void Write(System::String^ value) new;
virtual void Write(unsigned char value) new;
virtual void Write(unsigned int value) new;
virtual void Write(unsigned long long value) new;
virtual void Write(unsigned short value) new;
virtual void Write(wchar_t ch) new;
void Write7BitEncodedInt(int value);
*/
inline void WriteInt(const int& iValue) { Write<int>(&iValue, 1); }
};
_LF_END_
#endif
_Object.cpp
#include "_Object.h"
#include "_Debug.h"
#include "global_c_all.h"
_LF_BEGIN_
_int64 _Object::_iObjectCount = 0;
bool _Object::_bInitializeGlobal = false;
_Object::_Object()
{
#ifdef _OBJECT_DEBUG_
_cout << _t("_Object::_Object()\n");
#endif
++_iObjectCount;
if (!_bInitializeGlobal) {
setlocale(LC_ALL, "Chinese-simplified");//设置中文环境
_bInitializeGlobal = true;
}
}
_Object::~_Object()
{
#ifdef _OBJECT_DEBUG_
_cout << _t("_Object::~_Object()\n");
#endif
--_iObjectCount;
ClearData();
}
_string _Object::ToString() const
{
return _string();
}
_ByteArray& _Object::PackageMemory(_ByteArray& baPackageMem) const
{
// TODO: 在此处插入 return 语句
return baPackageMem;
}
/// <summary>
/// 从内存中读出对象
/// </summary>
/// <param name="pPackageMem">指向数据的指针</param>
/// <param name="nStart">开始读出的位置</param>
/// 创建时间:2022-11-13 最后一次修改时间:2023-03-12
void _Object::SplitFromMemory(const _byte* pPackageMem, const _uint nStart)
{
// TODO: 在此处插入 return 语句
}
int _Object::CompareTo(const _Object& oRight) const
{
_cout << _t("定义的对象:") << GetTypeName() + _t("需要重写虚拟函数 virtual int CompareTo(const _Object& oRight)\n");
return 1;
}
void _Object::TrusteeshipMem(const _byte* pData, const int nDataMemoryLength, const int& nMemoryLength)
{
ClearMemory();
}
_Object::operator _string()
{
return ToString();
}
/// <summary>
/// 从文件中读取数据
/// </summary>
/// 创建时间:2023-03-14 最后一次修改时间:2023-03-14
void _Object::ReadDataFromFile(const _string& sFullPathName)
{
if (ga.gcf_FileExisits(sFullPathName))
{
_ByteArray ba;
ba.ReadFromFile(sFullPathName);
this->SplitFromMemory(ba.Data);
}
else
{
d.ShowError(sFullPathName + _t(" 文件不存在!"));
}
}
/// <summary>
/// 把数据保存在文件中
/// </summary>
/// 创建时间:2023-03-14 最后一次修改时间:2023-03-14
void _Object::SaveDataToFile(const _string& sFullPathName)
{
if (ga.gcf_FileExisits(sFullPathName))
{
_ByteArray ba;
this->PackageMemory(ba);
ba.WriteToFile(sFullPathName);
}
else
{
d.ShowError(sFullPathName + _t(" 文件不存在!"));
}
}
/// <summary>
/// 获取一个文件名
/// </summary>
/// 创建时间:2023-03-14 最后一次修改时间:2023-03-14
_string _Object::GetFilePathName()const
{
_string sName = ClassName;
int n = sName.IndexOf(_t("::"));
if ( n != -1)
{
sName = sName.SubStr(n + 2, sName.Length - n - 2);
}
else
{
n = sName.IndexOf(_t(" "));
sName = sName.SubStr(n + 1, sName.Length - n - 1);
}
return ga.dataPath + sName + _t(".dat");
}
_string _Object::GetTypeName()const
{
std::wstring wText = gs.s_UTF8String_to_TextW(typeid(*this).name());
#ifdef _UNICODE_
#ifdef _USE_LF_
return wText.c_str();
#else
return wText;
#endif
#else
return str.s_wstring_to_string(wText);
#endif
}
/*
//------------------------------------------------------------------------------------CSharp
bool _Object::CSharp_Equals(const _Object& obj)
{
return false;
}
bool _Object::CSharp_Equals(const _Object& objA, const _Object& objB)
{
return false;
}
void _Object::Finalize()
{
}
int _Object::CSharp_GetHashCode()
{
return 0;
}
Type_ _Object::CSharp_GetType()
{
return Type_();
}
_Object& _Object::CSharp_MemberwiseClone()
{
return *this;
}
bool _Object::CSharp_ReferenceEquals(const _Object& objA, const _Object& objB)
{
return false;
}
_string _Object::CSharp_ToString()
{
return _string();
}
*/
_LF_END_
_File.cpp
#include "_File.h"
#include "X:\Work\Share\CCode\CPlatform\Base\global_c_all.h"
_LF_BEGIN_
_string _File::GetErrorText(const int iErrorCode)
{
switch (iErrorCode)
{
case 1 :
return _t("不允许执行该操作");
case 2:
return _t("没有此文件或目录");
case 3:
return _t("没有此进程");
case 4:
return _t("函数中断");
case 5:
return _t("I/O 错误");
case 6:
return _t("没有此设备或地址");
case 7:
return _t("参数列表太长");
case 8:
return _t("执行格式错误");
case 9:
return _t("文件编号错误");
case 10:
return _t("没有生成的进程");
case 11:
return _t("没有更多进程、没有足够内存或达到最大嵌套级别");
case 12:
return _t("没有足够内存");
case 13:
return _t("权限被拒绝");
case 14:
return _t("地址错误");
case 16:
return _t("设备或资源忙碌");
case 17:
return _t("文件已存在");
case 18:
return _t("跨设备链接");
case 19:
return _t("没有此设备");
case 20:
return _t("不是目录");
case 21:
return _t("是目录");
case 22:
return _t("参数无效");
case 23:
return _t("系统中打开的文件太多");
case 24:
return _t("打开的文件太多");
case 25:
return _t("不适当的 I / O 控制操作");
case 27:
return _t("文件太大");
case 28:
return _t("设备上没有剩余空间");
case 29:
return _t("搜寻无效");
case 30:
return _t("只读文件系统");
case 31:
return _t("链接太多");
case 32:
return _t("管道损坏");
case 33:
return _t("数学参数");
case 34:
return _t("结果太大");
case 36:
return _t("会发生资源死锁");
case 38:
return _t("文件名太长");
case 39:
return _t("无可用锁");
case 40:
return _t("函数不受支持");
case 41:
return _t("目录不为空");
case 42:
return _t("非法字节序列");
case 80:
return _t("字符串被截断");
default:
return _t("");
}
}
_BinaryWriter::_BinaryWriter(const _string& sFullPathName, const _FileMode& fm)
{
int iError;
switch (fm)
{
case _FileMode::Append:
iError = gcf.gcf_fopen_ext(&_pf, sFullPathName, _t("ab"));
break;
case _FileMode::Read:
iError = gcf.gcf_fopen_ext(&_pf, sFullPathName, _t("rb"));
break;
case _FileMode::Write:
iError = gcf.gcf_fopen_ext(&_pf, sFullPathName, _t("wb"));
break;
case _FileMode::AppendReadWrite:
iError = gcf.gcf_fopen_ext(&_pf, sFullPathName, _t("ab+"));
break;
case _FileMode::ReadWrite:
iError = gcf.gcf_fopen_ext(&_pf, sFullPathName, _t("rb+"));
break;
case _FileMode::WriteRead:
iError = gcf.gcf_fopen_ext(&_pf, sFullPathName, _t("wb+"));
break;
default:
iError = gcf.gcf_fopen_ext(&_pf, sFullPathName, _t("rb"));
break;
}
//打开一个文件
if (iError != 0) {
_string sError = _string(_t(" _BinaryWriter::_BinaryWriter() 打开文件错误:\t")) + _getc(sFullPathName) + _t("\n");
sError.Add(_t("错误信息是:"));
sError.Add(_File::GetErrorText(iError));
d.PrintError(sError);
}
}
_BinaryWriter::~_BinaryWriter()
{
if (_pf != null)
{
fclose(_pf);
_pf = null;
}
}
_BinaryReader::_BinaryReader(const _string& sFullPathName)
{
int iError = gcf.gcf_fopen_ext(&_pf, sFullPathName, _t("rb"));
//打开一个文件
if (iError != 0) {
_string sError = _string(_t(" _BinaryWriter::_BinaryWriter() 打开文件错误:\t")) + _getc(sFullPathName) + _t("\n");
sError.Add(_t("错误信息是:"));
sError.Add(_File::GetErrorText(iError));
d.PrintError(sError);
}
}
_BinaryReader::~_BinaryReader()
{
if (_pf != null)
{
fclose(_pf);
_pf = null;
}
}
int _BinaryReader::GetLength()
{
fseek(_pf, 0, SEEK_END); //定义到文件未尾
return ftell(_pf);
}
_ByteArray _BinaryReader::ReadAll()
{
_ByteArray baResult;
int nFileLength = Length;
if (nFileLength == 0) return baResult; //空文件
baResult.SetBuffer(nFileLength + 1);
rewind();
int nTrueCount = (int)fread(baResult.Data, 1, nFileLength, _pf);
if (nTrueCount != nFileLength)
{
d.PrintError(_t("_ByteArray _BinaryReader::ReadAll(): 读取数据长度错误!"));
}
baResult.ResetLength(nTrueCount);
baResult.ZeroBufferOne(); //把有效长度后一位置为0
return baResult;
}
int _BinaryReader::ReadInt()
{
int nResult;
int nTrueCount = (int)fread(&nResult, 1, sizeof(int), _pf);
if (nTrueCount != sizeof(int))
{
d.PrintError(_t("int _BinaryReader::ReadInt(): 读取Int数据长度错误!"));
}
return nResult;
}
_byte _BinaryReader::ReadByte()
{
_byte nResult;
int nTrueCount = (int)fread(&nResult, 1,1, _pf);
if (nTrueCount != 1)
{
d.PrintError(_t("_byte _BinaryReader::ReadByte(): 读取数据长度错误!"));
}
return nResult;
}
_ByteArray _BinaryReader::ReadByteArray(int nLength)
{
_ByteArray baResult;
baResult.SetBuffer(nLength + 1);
int nTrueCount = (int)fread(baResult.Data, 1, nLength, _pf);
if (nTrueCount != nLength)
{
d.PrintError(_t("_ByteArray _BinaryReader::ReadByteArray(int nLength): 读取数据长度错误!"));
}
baResult.ResetLength(nTrueCount);
baResult.ZeroBufferOne(); //把有效长度后一位置为0
return baResult;
}
_Str<wchar_t> _BinaryReader::ReadWString(const int& nMemoryLength)
{
_ByteArray ba;
ba.SetBuffer(nMemoryLength + 2);
int nTrueCount = (int)fread(ba.Data, 1, nMemoryLength, _pf);
if (nTrueCount != nMemoryLength)
{
d.PrintError(_t("_Str<wchar_t> _BinaryReader::ReadWString(const int& nCount): 读取数据长度错误!"));
}
ba.ResetLength(nTrueCount);
ba.ZeroBufferOne();
return _Str<wchar_t>::CopyFrom((wchar_t*)ba.Data, nMemoryLength / 2);
}
_Str<wchar_t> _BinaryReader::ReadOldWString(const int& nMemoryLength)
{
_ByteArray ba;
ba.SetBuffer(nMemoryLength + 2);
int nTrueCount = (int)fread(ba.Data, 1, nMemoryLength, _pf);
if (nTrueCount != nMemoryLength)
{
d.PrintError(_t("_Str<wchar_t> _BinaryReader::ReadOldWString(const int& nCount): 读取数据长度错误!"));
}
ba.ResetLength(nTrueCount);
ba.ZeroBufferOne();
#if _CLR_
return System::Text::Encoding::Default->GetString(ba);
#else
return _Str<wchar_t>::CopyFrom((wchar_t*)ba.Data, nMemoryLength / 2);
#endif
}
_LF_END_
_KeyBinaryFile.h
/*******************************************************************************************
文件名 : _KeyBinaryFile.h
作者 : 李锋
功能 : 依据关键字写入和读取内容
创建时间 : 2022年12月29日
---------------------------------------------最后一次修改时间 : 2022年12月29日
********************************************************************************************/
#ifndef __KEYBINARYFILE_H_
#define __KEYBINARYFILE_H_
#include "_DataType.h"
#include "_Object.h"
#include "_StrListW.h"
#include "_File.h"
#include "_ByteArray.h"
_LF_BEGIN_
/*
*1.override void Close()
关闭 BinaryWriter 对象和基础流。
2 virtual void Flush()
清理当前编写器的所有缓冲区,使得所有缓冲数据写入基础设备。
3 virtual long Seek(int offset,SeekOrigin origin )
设置当前流内的位置。
4 virtual void Write(bool value )
把一个单字节的布尔值写入到当前流中,0 表示 false,1 表示 true。
5 virtual void Write(byte value )
把一个无符号字节写入到当前流中,并把流的位置往前移一个字节。
6 virtual void Write(array<byte> buffer )
把一个字节数组写入到基础流中。
7 virtual void Write(char ch )
把一个 Unicode 字符写入到当前流中,并把流的当前位置按照所使用的编码和要写入到流中的指定的字符往前移。
8 virtual void Write(array<char> chars )
把一个字符数组写入到当前流中,并把流的当前位置按照所使用的编码和要写入到流中的指定的字符往前移。
9 virtual void Write(double value )
把一个 8 字节浮点值写入到当前流中,并把流位置往前移八个字节。
10 virtual void Write(int value )
把一个 4 字节有符号整数写入到当前流中,并把流位置往前移四个字节。
11 virtual void Write(String^ value )
把一个以长度为前缀的字符串写入到 BinaryWriter 的当前编码的流中,并把流的当前位置按照所使用的编码和要写入到流中的指定的字符往前移。
*/
/// <summary>
///============= 0 ============ ========== ========== ========== =============== 0 ============ ....
///记录个数int32 byte0 关键字长度int32 关键字 数据类型Byte 数据长度int32 数据 byte0 关键字长度int32
/// </summary>
class _KeyData : public _Object
{
public:
/// <summary>
/// 关键字,只读
/// </summary>
_Str<wchar_t> Keyword;
/// <summary>
/// 数据,byte数组,包含数据长度
/// </summary>
_ByteArray Data;
/// <summary>
/// 数据类型
/// </summary>
_DataType DataType;
public:
inline _KeyData(const _string& sKey) { Keyword = sKey; }
inline _KeyData() {}
inline virtual int CompareTo(const _Object& oRight)const override
{
_KeyData* kd = (_KeyData*)&oRight;
if (Keyword == kd->Keyword)
{
return 0;
}
else if (Keyword > kd->Keyword)
{
return 1;
}
else
{
return -1;
}
}
};
class _KeyBinaryFile : public _Object
{
private:
SortedDList<_KeyData> _kdList;
_string _FullPathName;
/// <summary>
/// 版本号,以区分以前的版本
/// </summary>
const static int _Version = 0;
/// <summary>
/// 是否以前的版本
/// </summary>
bool _bOldVer = false;
public:
/// <summary>
/// 是否旧版本文件
/// </summary>
/// <returns></returns>
inline bool IsOldVersion() const { return _bOldVer; }
inline SortedDList<_KeyData>& GetDataList() { return _kdList; }
inline int GetVersion() { return _Version; }
_KeyBinaryFile();
_KeyBinaryFile(const _Str<wchar_t>& sFullPathName, bool bReWrite = true);
void AddData(const _Str<wchar_t>& sKey, const _byte* pData, const int& nDataLength, const _DataType& kdtType);
inline void AddData(const _Str<wchar_t>& sKey, const _ByteArray& baData, const _DataType& kdtType)
{
AddData(sKey, baData.DataConst, baData.Length, kdtType);
}
inline void AddData(const _Str<wchar_t>& sKey, const _Str<wchar_t>& sValue) {
AddData(sKey, (_byte*)sValue.Data, sValue.Length * sizeof(wchar_t), _DataType::dtWString);
}
inline void AddInt64(const _Str<wchar_t>& sKey, const __int64 iValue)
{
AddData(sKey, (_byte*)(&iValue), sizeof(iValue), _DataType::dtInt64);
}
inline void AddString(const _Str<wchar_t>& sKey, const _Str<wchar_t>& sValue)
{
AddData(sKey, (_byte*)(sValue.Data), sValue.DataMemoryLength, _DataType::dtWString);
}
inline void AddByteArray(const _Str<wchar_t>& sKey, const _ByteArray& baData)
{
AddData(sKey, baData.DataConst, baData.Length, _DataType::dtInt8);
}
//============= 0 ============ ========== ========== ========== =============== 0 ============
//记录个数int32 byte0 关键字长度int32 关键字 数据类型Byte 数据长度int32 数据 byte0 关键字长度int32
void WriteKeyData(const _KeyData &kd, _BinaryWriter &bw);
void SaveAnother(const _string& anotherFileName, const bool &bReWrite = true);
inline void Save(const bool bReWrite = true) { SaveAnother(_FullPathName, bReWrite); }
void OpenAnoter(const _string& anotherFileName);
inline void Open() { OpenAnoter(_FullPathName); }
_string GetString(const _string& sKey, const _string &sDefaultValue = _t(""))const;
_KeyData* GetData(const _string& sKey) const;
_StringList GetIncludeKeyList(const _string& SubString);
static void FileRename(const _string& sFullPathName, const _string& sNewFileName);
};
_LF_END_
#endif
_KeyBinaryFile.cpp
#ifdef _CLR_
#include "X:\Work\Share\CCode\WindowsPlatform\CLR\Code\global_clr_all.h"
#endif
#include "_KeyBinaryFile.h"
#include "_Debug.h"
_LF_BEGIN_
/// <summary>
/// 版本号,以区分以前的版本
/// </summary>
//const int _KeyBinaryFile::_Version = 0;
_KeyBinaryFile::_KeyBinaryFile()
{
}
_KeyBinaryFile::_KeyBinaryFile(const _Str<wchar_t>& sFullPathName, bool bReWrite)
{
_FullPathName = sFullPathName;
}
/// <summary>
/// 添加一项数据,如果sKey存在,则覆盖。
/// </summary>
/// <param name="sKey"></param>
/// <param name="pData"></param>
/// <param name="nDataLength"></param>
/// <param name="kdtType"></param>
/// 创建时间:2022-12-31 最后一次修改时间:2022-12-31
void _KeyBinaryFile::AddData(const _Str<wchar_t>& sKey, const _byte* pData, const int& nDataLength, const _DataType& kdtType)
{
if (sKey.Length == 0 || sKey.CSharp_Trim().Length == 0)
{
_string sError = _t("void _KeyBinaryFile::addValue : sKey的度度不能为0,或sKey不能为空白字符!");
d.PrintError(sError);
throw sError.Data;
}
if (nDataLength <= 0)
{
_string sError = _t("void _KeyBinaryFile::addValue : baData长度0!");
d.ShowInfo(sError);
d.PrintError(sError);
return;
}
_KeyData* pkd = GetData(sKey); //查找一个存在的项
if (pkd != null) //已有sKey这个值,覆盖原来的数值。
{
pkd->Data.ClearMemory();
pkd->Data.Add(pData, nDataLength);
pkd->DataType = kdtType;
}
else
{
_KeyData kd;
kd.Keyword = sKey;
kd.Data.Add(pData, nDataLength);
kd.DataType = kdtType;
_kdList.Add(kd);
}
}
//============= 0 ============ ========== ========== ========== =============== 0 ============
//记录个数int32 byte0 关键字长度int32 关键字 数据类型Byte 数据长度int32 数据 byte0 关键字长度int32
void _KeyBinaryFile::WriteKeyData(const _KeyData& kd, _BinaryWriter& bw)
{
//写入边界
bw.WriteByte((_byte)0); //写入0
//-----------------------------------------------------------------------------------------------写入关键字长度与关键字
//array<byte>^ byteKeyWordArray = System::Text::Encoding::Default->GetBytes(kd->Keyword);
// int byteKeywordLen = byteKeyWordArray->Length;
//bw->Write(byteKeywordLen);
//bw->Write(byteKeyWordArray);
int nLen = kd.Keyword.Length * sizeof(wchar_t);
bw.Write<int>(&nLen, 1);
bw.Write<_byte>((_byte*)kd.Keyword.Data, kd.Keyword.Length * 2);
//-----------------------------------------------------------------------------------------------写入数据类型
bw.WriteByte((_byte)kd.DataType);
//---------------------------------------------------------------------------------写入数据长度 与 数据
bw.WriteInt(kd.Data.Length);
bw.Write<_byte>(kd.Data.GetDataConst(), kd.Data.Length);
}
void _KeyBinaryFile::SaveAnother(const _string& anotherFileName, const bool& bReWrite)
{
if (anotherFileName.CSharp_Trim().Length == 0)
{
_string sError = _t("void _KeyBinaryFile::SaveToFile: 文件名不能为空!");
d.PrintError(sError);
throw sError;
}
if (anotherFileName.IsInvalidPathName())
{
_string sError = _t("void _KeyBinaryFile::SaveToFile: 文件名格式不对!");
d.PrintError(sError);
throw sError;
}
if (anotherFileName.FileExists())
{
_string sError;
if (bReWrite)
{
if (!anotherFileName.FileDelete())
{
sError = _t("void _KeyBinaryFile::SaveToFile: 无法删除文件:") + anotherFileName;
d.PrintError(sError);
throw sError;
}
}
else
{
sError = _t("void _KeyBinaryFile::SaveToFile: 文件也存在!");
d.PrintError(sError);
throw sError;
}
}
//if (_slKey->Count == 0) return;
//写入文件,当_slKey->Count == 0时,只写入一个int数
_BinaryWriter bw(anotherFileName);
//首先写入版本号0
bw.WriteInt(_Version);
bw.WriteInt(_kdList.Count); //写入记录个数
// 写入文件
_DListNode<_KeyData>* dnNode = _kdList.First();
while (dnNode != null)
{
WriteKeyData(dnNode->Data, bw);
dnNode = dnNode->Next;
}
}
void _KeyBinaryFile::OpenAnoter(const _string& anotherFileName)
{
if (anotherFileName.FileExists()) //文件已存在,检查文件格式是否正确,如果正确,则加载文件内容
{
_kdList.ClearMemory();
_BinaryReader br(anotherFileName);
if (br.Length <= 4)
{
d.PrintError(_t("void _KeyBinaryFile::OpenAnoter(const _string& anotherFileName) : 空文件,或文件格式错误!"));
}
br.rewind(); //重置文件指针于开始位置
int iVersion = br.ReadInt();
if (iVersion == _Version)
{
_bOldVer = false;
}
else
{
d.ShowMessage(_t("旧版本文件!"),_t("void _KeyBinaryFile::OpenAnoter(const _string& anotherFileName)"));
_bOldVer = true;
br.rewind(); //重置到文件开头。
}
// 记录1 记录2
//============= ============ ==================== ======= =========== ============ ==== ======== ===============
//记录个数int32 (byte==0)边界 第一个关键字长度int32 关键字 数据类型Byte 数据长度int32 数据 byte0边界 第二个关键字长度
int nKeyDataCount = br.ReadInt(); //读取记录个数
for (int i = 0; i < nKeyDataCount; ++i)
{
_byte nByte = br.ReadByte();
if (nByte != 0) //边界
{
d.PrintError(_t("void _KeyBinaryFile::OpenAnoter(const _string& anotherFileName) :文件格式错误! nByte != 0 "));
return;
}
_KeyData kd;
int nMemKeyWordLen = br.ReadInt(); //关键字内存长度
if (!_bOldVer)
{
kd.Keyword = br.ReadWString(nMemKeyWordLen);
kd.DataType = (_DataType)br.ReadByte();
int nDataLength = br.ReadInt();
if (nDataLength <= 0 && nDataLength >= _Memory::_max_char)
{
d.PrintError(_t("void _KeyBinaryFile::OpenAnoter(const _string& anotherFileName) : 数据长度错误!"));
return;
}
kd.Data = br.ReadByteArray(nDataLength);
}
else //兼容旧版本文件,打开旧版本文件后,把旧版本所有类型为 dtString = 13, 类型的字符串全部转换为新格式文件。
{
kd.Keyword = br.ReadOldWString(nMemKeyWordLen);
kd.DataType = (_DataType)br.ReadByte();
int nDataLength = br.ReadInt();
if (nDataLength <= 0 && nDataLength >= _Memory::_max_char)
{
d.PrintError(_t("void _KeyBinaryFile::OpenAnoter(const _string& anotherFileName) : 数据长度错误!"));
return;
}
kd.Data = br.ReadByteArray(nDataLength);
if ( (int) kd.DataType == 13) //字符串 旧版本的值是13,这里不能改动
{
#if _CLR_
//解码格式重新赋值,否则保存以后还是变成旧的文件格式。
_StrW tmp = System::Text::Encoding::Default->GetString(kd.Data);
kd.Data.TrusteeshipMem(tmp);
#endif
}
}
_kdList.Add(kd);
}
if (_kdList.Count != nKeyDataCount)
{
d.PrintError(_t("void _KeyBinaryFile::OpenAnoter(const _string& anotherFileName) :文件记录数错误!"));
return;
}
}
else
{
_string sError = _t("void _KeyBinaryFile::OpenAnoter(const _string& anotherFileName) : 文件 \n") + anotherFileName + _t("不存在!");
d.ShowError(sError,_t("void _KeyBinaryFile::OpenAnoter(const _string& anotherFileName) :"));
}
}
/// <summary>
///
/// </summary>
/// <param name="sKey"></param>
/// <param name="sDefaultValue"></param>
/// <returns></returns>
/// 创建时间:2023-01-01 最后一次修改时间:2023-01-03
_string _KeyBinaryFile::GetString(const _string& sKey,const _string& sDefaultValue) const
{
_KeyData* pkd = GetData(sKey);
if (pkd != null)
{
return _string::CopyFrom((_char*)pkd->Data.Data, pkd->Data.Length / sizeof(_char));
}
return sDefaultValue;
}
_KeyData* _KeyBinaryFile::GetData(const _string& sKey) const
{
_DListNode<_KeyData>* dn = _kdList.First();
while (dn != null)
{
if (dn->Data.Keyword == sKey)
{
return &dn->Data;
}
dn = dn->Next;
}
return null;
}
/// <summary>
/// 获取KeyList,如果SubString为"",则为默认获取所有
/// </summary>
/// <param name="SubString">KeyWord中的子字符串</param>
/// <returns>返回KeyWord列表</returns>
_StringList _KeyBinaryFile::GetIncludeKeyList(const _string& SubString)
{
//throw gcnew Exception("请重写!");
_StringList slFind;
_DListNode<_KeyData>* First = _kdList.First();
while (First != null)
{
if (First->Data.Keyword.IndexOf(SubString) != -1)
slFind.Add(First->Data.Keyword);
First = First->Next;
}
return slFind;
}
/// <summary>
/// 把文件名重命名,包括备份文件
/// </summary>
/// <param name="sFullPathName">文件全路径</param>
/// <param name="sNewFileName">新文件名</param>
void _KeyBinaryFile::FileRename(const _string& sFullPathName, const _string& sNewFileName)
{
#ifdef _CLR_
gca::fd_FileRename(sFullPathName, sNewFileName, false);
//如果存在备份文件,也重新命名
gca::fd_FileRename((sFullPathName + ".bck"), sNewFileName + "." + sFullPathName.FileNameExt(), true);
#else
d.ShowError(_t("代码未完成!"));
#endif
}
_LF_END_