Um boa rotina de persistência na abertura de DBFs ajuda muito tanto quanto aos acessos em rede como podem vir a ser complementado com a integridade do arquivo. Por isso exponho um exemplo de como venho empregando a rotina de abertura DBF com auto-reconhecimento do RDD a ser utilizado.
A função
DBUSEAREA( [<lNewArea>], [<cDriver>], <cName>, [<xcAlias>], [<lShared>], [<lReadonly>]) utiliza como opção o driver RDD a ser usado. Então nada melhor que utilizar também a rotina de auto-reconhecimento desse driver.
Rotina de abertura de DBFs:
Function Open_Dbf(cDbfName, lUseExclusive, lReadonly, cAlias, cRddName, nTries, lAsk)
Local nTriesOrig, lReturn:=.f., lNewArea:=.t.
DEFAULT lNewArea:=.t.
DEFAULT lReadonly:=.f.
DEFAULT lAsk:=.t.
DEFAULT nTries:=5
DEFAULT cRddName:=GetDbfType(cDbfName,4)
nTriesOrig := nTries
Do While nTries > 0
DbUseArea(lNewArea,cRddName,cDbfName,cAlias,!lUseExclusive,lReadonly)
If (!NetErr()) .and. Used()
lReturn := .t.
Exit
Endif
Inkey(.5)
nTries--
If nTries = 0 .and. lAsk
If MsgRetryCancel("Database is occupied by another user","No access" )
nTries := nTriesOrig
Endif
Endif
Enddo
Return lReturn
Rotina para auto-reconhecimento do tipo do DBF:
#define HEXTABLE "0123456789ABCDEF"
Function GetDbfType(cDataBase,nRet)
Local nHandle, cDbfHead, cMemoC:="", cMemoD:="", nPos, cRet:=""
Local aMemoC:={"0x02","0x03","0x04","0x30","0x31","0x43","0x63","0x83","0x8B","0x8C","0xCB","0xE5","0xEB","0xF5","0xFB","0x54","0xA7","0xB9","0xE2","0xEF"}
Local aMemoD:={{"FoxBase","","DBFCDX"},;
{"dBASE III, dBASE IV, dBASE 5, dBASE 7, FoxPro, FoxBASE+","","DBFNTX"},;
{"dBASE 7","","DBFNTX"},;
{"Visual FoxPro","FPT","DBFCDX"},;
{"Visual FoxPro","","DBFCDX"},;
{"dBASE IV, dBASE 5","","DBFNTX"},;
{"dBASE IV, dBASE 5","","DBFNTX"},;
{"dBASE III, FoxBase+, FoxPro","DBT","DBFNTX"},;
{"dBASE IV, dBASE 5","DBT","DBFNTX"},;
{"dBASE 7","DBT","DBFNTX"},;
{"dBASE IV, dBASE 5","DBT","DBFNTX"},;
{"SMT","SMT","DBFNSX"},;
{"dBASE IV, dBASE 5","DBT","DBFNTX"},;
{"FoxPro","FPT","DBFCDX"},;
{"FoxBase","","DBFCDX"},;
{"dBASE IV with SQL","DBT","DBFNTX"},;
{"FoxPro 2.x (or older)","DBT","DBFNTX"},;
{"FoxBase","","DBFNTX"},;
{"dBASE III+ or FoxBase+","DBT","DBFNTX"},;
{"dBASE IV","DBT","DBFNTX"}}
If ( nHandle := FOpen( cDataBase, FO_READ ) ) == - 1
MsgStop('Can not open file '+Upper(cDataBase)+' for reading !')
Return ""
Endif
cDbfHead:=Space(4)
FRead( nHandle, @cDbfHead, 4 )
FClose( nHandle )
cMemoC:="0x"+FT_BYT2HEX(SubStr(cDbfHead,1,1))
nPos:=AScan(aMemoC,cMemoC)
If nPos>0
If nRet=1
cRet:=cMemoC
Else
cRet:=aMemoD[nPos,(nRet-1)]
Endif
Endif
Return cRet
Function FT_BYT2HEX(cByte,lPlusH)
Local xHexString
Default lPlusH := .f.
If ValType(cByte) == "C"
xHexString := SubStr( HEXTABLE, Int(Asc(cByte) / 16) + 1, 1 ) ;
+ SubStr( HEXTABLE, Int(Asc(cByte) % 16) + 1, 1 ) ;
+ Iif(lPlusH, "h", '')
Endif
Return xHexString
O código foi escrito em Harbour/HMG, mas pode ser facilmente adaptado para Clipper. Se alguém tiver mais alguma ideia melhor sobre a rotina de persistência será bem vinda !
:)Pos