?? 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; // 返回比較當前位移
/***
***/
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 + -