在實際的開發過程中,我們可能需要在檔案生成時就立即将檔案更改為指定的大小,以便于後續簡化對檔案的并發操作,
這一點在各類的下載下傳工具中有很好的展現。
要滿足這一需求,通常可以使用的最直覺的方式是:生成檔案後,通過循環向檔案中寫入任意資料,直到檔案大小達到預期的大小。
對于較小的檔案,這種方法可以接受,但是如果檔案大小過大,那麼這種方法就顯得不夠簡潔且低效。
這裡介紹一種高效且簡單的方法,基于函數"lseek"。
執行"man lseek"之後,我們可以看到關于lseek特性的關鍵資訊,如下:
The lseek() function shall allow the file offset to be set beyond the end of the existing data in the file.
If data is later written at this point, subsequent reads of data in the gap shall return bytes with the
value 0 until data is actually written into the gap.
The lseek() function shall not, by itself, extend the size of a file.
簡單的總結就是:
1. lseek 函數本身不會擴充檔案的大小.
2. lseek 允許檔案的偏移值超過檔案的末端,如果下一次在這個偏移點寫入資料,那麼在偏移之前的檔案末端與偏移點之間的資料将會自動填充為0。
了解了上面幾點,大家應該想到了擴充檔案大小将是一件多麼簡潔高效的事情了:)
//! @brief 擴充檔案大小
boolEnlargeFile(intiFileHandle , off_t iNewSize )
{
if( ( iFileHandle<0)||( iNewSize<0) )
{
LOG_DEBUG_INFO("parameter for is not valid", iFileHandle , iNewSize );
returnfalse;
}
structstat fileState;
intiStatus=fstat( iFileHandle ,&fileState );
if(0!=iStatus )
{
LOG_DEBUG_INFO("invoke fail , ErrCode:%d , ErrMsg:%s", \
iFileHandle ,&fileState , errno , strerror( errno ) );
returnfalse;
}
constoff_t iCurSize=fileState.st_size;
if( iNewSize<=iCurSize )
{
LOG_DEBUG_INFO("new file size = %ld , current file size = %ld , can not resize file to smaller size.", \
iNewSize , iCurSize );
returnfalse;
}
constoff_t iCurPos=lseek( iFileHandle ,0, SEEK_CUR );//儲存檔案指針的目前位置以便于在擴充檔案大小後恢複到目前位置
if( iCurPos<0)
{
LOG_DEBUG_INFO("invoke fail , ErrCode:%d , ErrMsg:%s", \
iFileHandle , errno , strerror( errno ) );
returnfalse;
}
constoff_t iMoveOffset=iNewSize-1;
iStatus=lseek( iFileHandle , iMoveOffset , SEEK_SET );
if( iStatus!=iMoveOffset )
{
LOG_DEBUG_INFO("invoke fail , ErrCode:%d , ErrMsg:%s", \
iFileHandle , iMoveOffset , errno , strerror( errno ) );
returnfalse;
}
constintWRITE_BYTE_COUNT=1;
iStatus=write( iFileHandle ,"", WRITE_BYTE_COUNT );//寫入一個位元組的資料,完成對檔案大小的更改
if( iStatus!=WRITE_BYTE_COUNT )
{
LOG_DEBUG_INFO("invoke fail , ErrCode:%d , ErrMsg:%s", \
iFileHandle , WRITE_BYTE_COUNT , errno , strerror( errno ) );
returnfalse;
}
iStatus=lseek( iFileHandle , iCurPos , SEEK_SET );//恢複檔案指針到之前儲存的檔案位置
if( iStatus!=iCurPos )
{
LOG_DEBUG_INFO("invoke fail , ErrCode:%d , ErrMsg:%s", \
iFileHandle , iCurPos , errno , strerror( errno ) );
returnfalse;
}
returntrue;
}
點選下載下傳
Linux manpages CHM檔案下載下傳:
Linux_manpages_part_1_of_4
Linux_manpages_part_2_of_4
Linux_manpages_part_3_of_4
Linux_manpages_part_4_of_4
(由于cppblog限制單個檔案上傳大小,這裡将CHM分割成4部分,全部下載下傳後解壓即可).
如果下載下傳速度太慢,請前往這裡下載下傳.
posted on 2010-03-01 21:48 luckycat 閱讀(5613) 評論(5) 編輯 收藏 引用 所屬分類: Linux