📄 usortfile.cpp
字号:
if(BytesRead != NULL)
*BytesRead = -1;
goto __ENDREAD__;
}
// 若 nOffset 大于 0 , 则为指定位置读取数据,否则从文件头部读取
if ( nOffset >= 0 )
zfseek (zfp, nOffset, ZSEEK_SET);
else
{
// 参数错误也返回失败
// zfseek (zfp, 0, ZSEEK_SET ); close 2002/12/09
bRet = FALSE;
*BytesRead = -1;
goto __ENDREAD__;
}
// 读取数据
nRead = zfread ( ReadBuff, sizeof(char), BytesToRead, zfp);
if (nRead != (int)BytesToRead)
{
bRet = FALSE;
*BytesRead = nRead;
goto __ENDREAD__;
}
*BytesRead = nRead;
__ENDREAD__:
return bRet;
}
////////////////////////////////////////////////////////////////////////////////////////
// 功能说明 : 在排序文件中进行二分查找,并返回最后一次比对的位移
// 输入参数 : CompBuff 比较缓冲(关键字)
// 输入参数 : nRecOffset 比对(关键字)在记录中的位移
// 输入参数 : nCompBytes 比对(关键字)长度
// 输出参数 : nCompResult 比对结果,-2 代表比对失败,-1 0 1 代表小于等于大于文件位移的记录
// 返回值 : long 最后一次的位移
////////////////////////////////////////////////////////////////////////////////////////
long CSortRecordFile::FindRecord(
IN const void *CompBuff,
IN unsigned int nRecOffset,
IN unsigned int nCompBytes,
OUT int *nCompResult
)
{
char * szReadBuff = NULL ; // 读取报文缓存
int nLow = 0; // 二分查找临时变量 low, high, mid, times.
int nHight = 0;
int nMid = 0;
int nTimes = 0;
int nRead = 0; // 读取字节数
int nCmpRet = 0; // 比较结果
int nMaxRecCount = 0; // 最大记录数
long nSearchOffset = -1L; // 返回比较当前位移
/***
* 准备处理查找, Result = -2 表示非法参数或准备失败
***/
if ( zfp == NULL || CompBuff == NULL || nCompResult == NULL )
{
if(nCompResult != NULL)
*nCompResult = -2;
return -1L;
}
if ( nRecOffset > m_nRecLen )
{
*nCompResult = -2;
return -1L;
}
szReadBuff = (char*) malloc (sizeof(char) * m_nRecLen + 1 );
if ( szReadBuff == NULL )
{
*nCompResult = -2;
return -1L;
}
else
memset (szReadBuff, 0, m_nRecLen + 1);
/***
* 求文件最大记录数
***/
nMaxRecCount = GetRecordCount();
nHight = nMaxRecCount - 1;
if ( nHight < 0)
{
*nCompResult = -1;
return 0;
}
/***
* 在文件记录中进行二分查找
***/
nTimes = 0;
while ( ( nTimes < (int)nMaxRecCount ) && ( nLow <= nHight ) )
{
nTimes ++ ;
nMid = ( nLow + nHight ) / 2;
memset ( szReadBuff , 0 , m_nRecLen + 1 ) ;
zfseek ( zfp , nMid * ( m_nRecLen ) + m_nStartOffset, ZSEEK_SET ) ;
nRead = zfread ( szReadBuff , sizeof(char), (int)m_nRecLen , zfp ) ;
if ( nRead != (int)m_nRecLen ) // 文件读取失败
{
*nCompResult = -2;
nSearchOffset = -1;
break;
}
/***
* 根据比对结果分别对返回值进行赋值
***/
nCmpRet = memcmp ( CompBuff, szReadBuff+nRecOffset, nCompBytes ) ;
nSearchOffset = zftell(zfp) - m_nRecLen;
if ( nCmpRet == 0 ) // CompBuff == szReadBuff+nRecOffset
{
*nCompResult = 0;
break;
}
else if ( nCmpRet < 0 ) // CompBuff < szReadBuff+nRecOffset
{
*nCompResult = -1;
nHight = nMid - 1 ;
}
else if ( nCmpRet > 0 ) // CompBuff > szReadBuff+nRecOffset
{
*nCompResult = 1;
nLow = nMid + 1 ;
}
}
/***
* 比对结束,返回结果
***/
/*__ENDFIND__:*/
if(szReadBuff != NULL)
free(szReadBuff);
szReadBuff = NULL ;
return nSearchOffset ;
}
////////////////////////////////////////////////////////////////////////////////////////
// 功能说明 : 在缓冲中模糊搜索数据
// 输入参数 :
// 返回值 : BOOL
////////////////////////////////////////////////////////////////////////////////////////
BOOL CSortRecordFile::BlueSearchData (
const void *szSrcData,
unsigned int nSrcLen,
const void *szDestData,
unsigned int nDestLen
)
{
BOOL bRet = 0;
char *szSrcStr = NULL;
char *szDestStr = NULL;
szSrcStr = (char*) malloc ( sizeof(char)*nSrcLen + 1 );
szDestStr = (char*) malloc ( sizeof(char)*nDestLen + 1 );
if ( szSrcStr == NULL || szDestStr == NULL )
{
bRet = FALSE;
goto _END_BLUESEARCHDATA_;
}
memset ( szSrcStr, 0, nSrcLen+1 );
memset ( szDestStr, 0, nDestLen+1 );
memcpy ( szSrcStr, szSrcData, nSrcLen );
memcpy ( szDestStr, szDestData, nDestLen );
if ( strstr(szSrcStr, szDestStr ) != NULL )
bRet = TRUE;
else
bRet = FALSE;
_END_BLUESEARCHDATA_:
MFree(szSrcStr);
MFree(szDestStr);
return bRet;
}
///////////////////////////////////////////////////////////////////////////////////////
// 功能说明 : 在排序文件中进行块读模糊查找,并返回查找到第一条记录的相对位移
// 输入参数 : CompBuff 比较缓冲
// 输入参数 : nRecOffset 比对内容在记录中的相对位移
// 输入参数 : nCompBytes 比对长度
// 输出参数 : nCompResult 比对结果,0 代表查找失败,> 0 表示实际查找到记录条数
// 返回值 : long 查找第一条记录相对位移
////////////////////////////////////////////////////////////////////////////////////////
long CSortRecordFile::BlueSearchRecord (
IN const void *szCompBuff,
IN unsigned int nRecOffset,
IN unsigned int nCompBytes,
OUT int *nCompResult
)
{
int nBlockRecCount = 0;
int nRead = 0;
int nRecCount = 0;
long nOffset = 0L;
long nFileEndOffset = 0L;
char *szBlockReadBuff=NULL;
// 能找到则加一,否则为 0
nCompResult = 0;
// 申请块读缓冲区, 最大4K
if ( m_nRecLen > 4096 )
nBlockRecCount = 1;
else
nBlockRecCount = 4096/m_nRecLen;
szBlockReadBuff = (char*) malloc ( sizeof(char)*(nBlockRecCount)*(m_nRecLen) );
if(szBlockReadBuff == NULL )
{
printf("内存申请失败\n");
return -1L;
}
memset ( szBlockReadBuff, 0, (nBlockRecCount)*(m_nRecLen) );
if (zfp == NULL)
{
printf("文件未打开\n");
return -1L;
}
// 从尾部往后倒查文件
zfseek (zfp, 0, ZSEEK_END);
nFileEndOffset = zftell(zfp);
nOffset = -1;
while (1)
{
// 文件长度及尾部位移大于一块长度
if ( nFileEndOffset >= nBlockRecCount * (int)m_nRecLen )
{
nFileEndOffset -= nBlockRecCount * m_nRecLen;
zfseek ( zfp, nFileEndOffset, ZSEEK_SET );
}
else if ( nFileEndOffset > 0 ) // 剩余部分不足一块
{
nFileEndOffset = -1; // 为退出准备条件
zfseek ( zfp, 0, ZSEEK_SET );
}
else
{
break;
}
memset ( szBlockReadBuff, 0, nBlockRecCount*m_nRecLen );
nRead = zfread ( szBlockReadBuff, sizeof(char), nBlockRecCount*m_nRecLen, zfp );
if(nRead <= 0)
break;
nRecCount = nRead / m_nRecLen;
for ( int i = 0; i < nRecCount; i ++ )
{
if ( BlueSearchData (szCompBuff, nCompBytes, szBlockReadBuff+i*m_nRecLen+nRecOffset, nCompBytes) )
{
nOffset = zftell(zfp) - nRecCount*m_nRecLen + i*m_nRecLen;
++nCompResult;
nFileEndOffset = -1; // 作为结束标志
break;
}
}
}
free(szBlockReadBuff);
szBlockReadBuff=NULL;
zfclose(zfp);
return nOffset;
}
////////////////////////////////////////////////////////////////////////////////////////
// 功能说明 : 获取文件记录个数(记录长度为定长)
// 输入参数 : VOID
// 输出参数 : VOID
// 返回值 : int
////////////////////////////////////////////////////////////////////////////////////////
int CSortRecordFile::GetRecordCount (void)
{
int nRecCount = 0;
long nFileEndOffset = 0L;
if ( zfp == NULL || (int)m_nRecLen <= 0 )
return 0;
else
zfclose (zfp);
zfp = zfopen ( m_szFileName, "r+" );
if ( zfp == NULL )
return 0;
zfseek ( zfp, 0, ZSEEK_END );
nFileEndOffset = zftell (zfp);
nFileEndOffset -= m_nStartOffset;
if (nFileEndOffset < 0 )
nFileEndOffset = 0;
nRecCount =
nFileEndOffset / m_nRecLen + ((nFileEndOffset % m_nRecLen) ? 1 : 0 ) ;
return nRecCount;
}
////////////////////////////////////////////////////////////////////////////////////////
// 功能说明 : 获取排序文件总字节数
// 输入参数 : VOID
// 输出参数 : VOID
// 返回值 : long
////////////////////////////////////////////////////////////////////////////////////////
long CSortRecordFile::GetFileBytes (void)
{
long nFileEndOffset = 0L;
if ( zfp == NULL )
return 0L;
else
zfclose (zfp);
zfp = zfopen ( m_szFileName, "r+" );
if ( zfp == NULL )
return 0L;
// 获取文件记录长度
zfseek ( zfp, 0, ZSEEK_END ) ;
nFileEndOffset = zftell(zfp);
if ( nFileEndOffset < 0 )
nFileEndOffset = 0;
// 返回结果
return nFileEndOffset;
}
////////////////////////////////////////////////////////////////////////////////////////
// 功能说明 : 把文件在某偏移量后的数据向后移动某偏移量
// 输入参数 : nMoveBeginOffset 开始偏移位置
// 输入参数 : nMoveOffset 移动偏移位置(正代表后移,负代表前移)
// 输出参数 : VOID
// 返回值 : BOOL
// 注意 : 本函数可以较快地移植到其他环境下使用
////////////////////////////////////////////////////////////////////////////////////////
BOOL CSortRecordFile::MoveRecordAfterOffset(
unsigned long nMoveBeginOffset,
long nMoveOffset
)
{
int nRead = 0; // 读取字节
int nWritten = 0; // 写入字节
long nFileBytes = 0L; // 总字节数
long nFileBytesToMove = 0L; // 文件总共需要移动的字节数
long nBlockToReadBytes = 0L; // 当前需要读字节数
long nCurrReadOffset = 0L; // 当前文件读取文件指针位移
unsigned char *szBlockReadBuff = NULL;
BOOL bMoveRet = TRUE;
/***
* 准备移动数据
***/
// 准备移动文件内容,文件未打开或参数非法返回失败
if ( zfp == NULL || nMoveOffset == 0 )
{
return FALSE;
}
// 申请块读缓冲区
szBlockReadBuff =
(unsigned char*) malloc ( sizeof(char)*(RECCNT_PERBLK)*(m_nRecLen) );
if(szBlockReadBuff == NULL )
{
printf ("malloc memory fail\n");
return FALSE;
}
// 求出总共需要移动的字节数
nFileBytes = GetFileBytes ();
if ( nFileBytes == 0 ) // 文件长度为零
{
free(szBlockReadBuff);
return TRUE;
}
nFileBytesToMove = nFileBytes - nMoveBeginOffset;
if ( nFileBytesToMove < 0 ) // 文件长度小于起始位置
{
free(szBlockReadBuff);
return FALSE;
}
/***
* 根据 nMoveOffset 分别移动数据
***/
// 若位移为负(前移数据)从当前位置开始搬运数据
// * * * | * * *
// 1 2 3 4 5 6
// <====
if ( nMoveOffset < 0 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -