Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Theres a trick to solve error "Not Dbf file" ?

Status
Not open for further replies.

NICKYSUWANDI

Programmer
Jan 8, 2004
80
0
0
ID
I got this message when open file .dbf "Not Dbf/Database file" and this file cann't opened, but can opened with Ms Excel (only happend in WIndows 98 and when the application that i made use this .dbf is hang).
Some can give trick in program so i can fix this problem.
i am using Foxprow For windows 2.6a

Thanks

Nicky
 
i am creating program from Foxprow For windows 2.6a, when this program running sometimes it's hang, when this program hang cause my .dbf error (not all .dbf, just one of them). this .dbf only can opened with Ms Excell, when opened with foxprow it will appear error "Not .dbf file".
i don't what wrong in my program coding?
 
In most cases this problem is because of difference between
physichal record number and value of "number of records in
file" (DBF file 4-7 bytes, longint).
Because of freezing the Foxpro can't refresh this value,
although the record is wrote into the file. The program
should cut the size of the file fitted to the value in the
header (above).
 
The first byte number is 0. And so you have to calculate the
4-7 bytes.
 
In addition to the advice you already received, I suggest to download this little utility to find out the type of your dbf file.

What type is this DBF file
thread182-926493

Also you could use this faq:
How to read a DBF Header and get info about it
faq182-3161

Both were written by rob444.
 
In addition to the record count defined in bytes 4-7, you
could add some additional overhead to your application
that writes any table insertions to a temporary file
before making the insertion into the target table.

That way, if your application freezes during updating
the record count, and after restarting the application,
you can trap on not a DBF error, open the file low-level,
adjust the file size to the record count, close the
low-level instance, reopen, perform any re-indexing, and
finally insert the lost record.

This of course requires getting exclusive access to the
table, and having a rock-solid algorithm to calculate
the correct file size, etc...

Darrell

Here's some example code:
Code:
* [URL unfurl="true"]http://www.tek-tips.com/viewthread.cfm?qid=1007490&page=1[/URL]
* FoxPro Platforms: All

private cTempTable, i

cTempTable = substr(sys(2015),3,10)

* Create a test table, add 100 records, and close it
create table (sys(2023)+"\"+cTempTable) (field1 c(10))
for i = 1 to 100
  insert into (cTempTable) (field1) values ("Field"+allt(str(i)))
next

wait "Table has "+allt(str(reccount()))+" records" window
use

* Get info on table
private nRecs, n1stRec, nLenRecs
store 0 to nRecs, n1stRec, nLenRecs

=GetTableInfo(sys(2023)+"\"+cTempTable+".dbf",@nRecs, @n1stRec, @nLenRecs)

* Drop last record of table by truncating it's files size
=DropLstRec(sys(2023)+"\"+cTempTable+".dbf", nRecs, n1stRec, nLenRecs)

* Set a error handler and try to open table that was munged above
on error do errHand with error(), message(), message(1)
* Try to open table
use sys(2023)+"\"+cTempTable+".dbf"

* Release error handler
on error

wait "If you see this, table was fixed!" window
wait "Table now has "+allt(str(reccount()))+" records" window nowait

use

* Error handler
procedure errHand
  parameters nErr, cMsg1, cMsg2
  if nErr == 15 && Not a DBF
    if DecRecCount(eval(substr(cMsg2,at(" ",cMsg2)+1)))
      retry
    else
      wait "Failure!" window timeout 3
      return to master
    endif
  endif


  * Return the reccount, position of 1st data record,
  * and the data record length for a table
function GetTableInfo
  parameter cTableName, nRecCount, nPos1stRec, nLenOfRecs
  private nFlHandle, bSuccess

  if file(cTableName)

    nFlHandle = fopen(cTableName)
    bSuccess = nFlHandle <> -1
    if bSuccess

      =fseek(nFlHandle,4,0)

      nRecCount  = fread(nFlHandle,4)
      nPos1stRec = fread(nFlHandle,2)
      nLenOfRecs = fread(nFlHandle,2)

      =fclose(nFlHandle)

      nRecCount = ;
        asc(left(nReccount,1)) + ;
        asc(substr(nReccount,2,1)) * 256 + ;
        asc(substr(nReccount,3,1)) * 65536 + ;
        asc(substr(nReccount,4,1)) * 16777216

      nPos1stRec = ;
        asc(left(nPos1stRec,1)) + ;
        asc(substr(nPos1stRec,2,1)) * 256

      nLenOfRecs = ;
        asc(left(nLenOfRecs,1)) + ;
        asc(substr(nLenOfRecs,2,1)) * 256

    endif
  endif
  return bSuccess

  * Drop last record in a table
procedure DropLstRec
  parameter cTable, nRecs, n1stRec, nLenRecs
  private nTableSize, nFlHandle, nMovePointer
  if file(cTable)

    nFlHandle = fopen(cTable,1) && Write only

    if nFlHandle <> -1

      nRecs = nRecs - 1 && New record count
      nMovePointer = n1stRec + nLenRecs * nRecs + 1 && Position at end of new record count

      =fseek(nFlHandle,nMovePointer,0)

      =fwrite(nFlHandle,chr(26)) && Write eof marker

      * Change file size
      =fchsize(nFlHandle,nMovePointer+1) && +1 Compensates for eof marker

      =fclose(nFlHandle)
    endif
  endif

  * Decrement a table's record count
procedure DecRecCount
  parameter cTable
  * Hide previously defined variables
  private nFlHandle, nRecs, n1stRec, nLenRecs, bSuccess
  store 0 to nRecs, n1stRec, nLenRecs, cRecs

  if GetTableInfo(cTable,@nRecs, @n1stRec, @nLenRecs)
    cRecs = Int2Long(nRecs - 1)
    nFlHandle = fopen(cTable,1)
    bSuccess = nFlHandle <> -1
    if bSuccess
      =fseek(nFlHandle,4,0)
      =fwrite(nFlHandle,cRecs)
      =fclose(nFlHandle)
    endif
  endif
  return bSuccess

  * Convert a 32 bit value to a "Big-Endian" Long value
function Int2Long
  parameter nDecVal
  private nDecVal, cLongStrVal
  cLongStrVal = ""
  for i = 24 to 0 step -8
    cLongStrVal = chr(int(nDecVal/(2^i))) + cLongStrVal
    nDecVal = mod(nDecVal, (2^i))
  next
  return cLongStrVal
 
Review faq182-8 and possibly try using FixDBF as mentioned in thread182-799130 or thread182-35298. Years ago when I had to fix some DBFs I first hacked the table header to make it appear it had more records than it could possibly have, then I ran the fix program, either dSalvage or FixDBF, I don't remember which, which then shortened my hacked count to the acutal number of records really there.

Although you don't mention using Visual FoxPro, be aware that if you use the table in a mixed FP/VFP environment, then don't PACK the table in VFP or you'll have to copy the table with TYPE FOX2X as thread184-749265 mentions.
 
As many have already suggested, hacking the header will work, as will all the utilities suggested.

Another trick I found years ago, was to open the table
with MFOXPLUS, the Foxbase forerunner to Foxpro. You could open the table exclusively, pack it, and then the table would open in Foxpro.

I also seem to remember years back writing my own fox database fixer using fopen and fwrite commands. A foxpro developed fix for damaged foxpro files.




Sweep
...if it works dont mess with it
 
Try using a program like dsalvage to repair the damaged table.
 
You can use Filefix from Symantec (Old version of Norton Utilities).

To avoid your DBF From Not A DBF File, use :
Set autosave on

and each time after replace command don't forget to add :
flush (see help for detail)

Hope this work.
 
VFP doesn't seem to care about the header count, but it DOES update it ... so, this is what I do and it works great:

in VFP,
USE the file
APPEND a record
DELETE the appended record

Header count fixed! I have written a program in VFP that allows selection of a file, and then "fixes" it by the above method. I am assuming you have VFP available to use to "fix" these FPD2.6 files.
 
The record count could be wrong or the last byte of the file at HEADER()+RECSIZE()*RECCOUNT()+1 which should be a CHR(26) ^Z may be changed or missing.

The referenced utilities had no source code and the code posted in this thread was a bit confusing because it was a sample and not a utility. I decided I've needed a DBFFIX for a long time and just for fun, I wrote it in FOX. As a FOX source, you can include DBF fixing in your runtime projects if necessary. This code was created and tested for a couple of hours today so it may not be as full featured as other DBF recovery products. Unfortunately, it is so rare that I run into a damaged DBF, my ability to test it further will be limited. Let me know if there are problems.

DO DBFFIX WITH "BAD.DBF",.t.,.t.,.t.

* DBFFIX.PRG by severach 3/23/2005
* Written & Tested under FOXPRO-DOS 2.5
*To test, find a DBF, use HIEW.EXE (Hex-Edit) and Truncate the last record.
* 1) Truncate only the ^Z
* 2) Truncate partway into a record
* 3) Truncate all but the DELE() column
* 4) Truncate a few records
* 5) Adjust RECCOUNT() down
*do dbffix1 with "a2.dbf",.t.,.f.,.t.

*This programs assumes that the header length and record length are correct.

*xin, file to fix
*xfix, true to fix, false to show results only
*xpad, true to pad last damaged record instead of truncate
*xreco, true to recover extra records found at the end
*proc dbffix1
parameter xin,xfix,xpad,xreco
clos data
clos all
set talk off
?
?iif(xfix,"Examining","Fixing")+" file "+xin
fi=fopen(xin,iif(xfix,12,10))
if fi>=0 then
hdr=fread(fi,12)
nr=asc(substr(hdr,5,1))+256*asc(substr(hdr,6,1))+65536*asc(substr(hdr,7,1))+16777216*asc(substr(hdr,8,1))
hl=asc(substr(hdr,9,1))+256*asc(substr(hdr,10,1))
rl=asc(substr(hdr,11,1))+256*asc(substr(hdr,12,1))
?"Header Information"
?" Recs ="+str(nr,10)+" records"
?" Header ="+str(hl,10)+" bytes"
?" Record ="+str(rl,10)+" bytes"
?" Calc len="+str(hl+nr*rl,10)+" bytes"
?
?"Analyzing"
needfix=.f.
high=fseek(fi,0,2)
nr2=(high-hl)/rl-nr
pos=fseek(fi,high-1)
if pos>hl+nr*rl then
?" File is too large by "+allt(str(nr2,10,2))+" records, "
if ((xpad and nr2>=0) or nr2>=1) and xreco
??"recovering"
needfix=.t.
else
??"will truncate"
high=fseek(fi,hl+nr*rl+1)
pos=fseek(fi,high-1)
needfix=.t.
endif
endif
release nr2
if pos+1 == hl+nr*rl
?" No data lost"
pos=fseek(fi,pos+1)
ctlz=chr(0)
nr2=nr
else
if pos==hl+nr*rl
?" All records present"
else
?" Record count may be adjusted"
needfix=.t.
endif
ctlz=fread(fi,1)
nr2=int((pos-hl)/rl)
endif
?" Act len ="+str(pos,10)
if ctlz==chr(26) then
?" Ctrl-Z mark found ;)"
else
?" Ctrl-Z mark not found ;("
needfix=.t.
endif
?
if needfix then
?"Fixing"+iif(xfix,""," (write disabled)")
if xpad then
pos=fseek(fi,high)
if pos>hl+nr2*rl+1 && if there's only a DELE(), don't save it
?" Padding last record"
nr2=nr2+1
need=hl+nr2*rl-pos
=fwrite(fi,repl(chr(0),need),need) && need to write bytes that are MEMO safe
else
if pos#hl+nr2*rl+1
?" Unable to pad"
endif
endif
endif
?" New calculated records"+str(nr2,10)
pos=fseek(fi,hl+nr2*rl)
=fwrite(fi,chr(26),1)
?" ^Z written"
=fchsize(fi,hl+nr2*rl+1)
if nr2#nr then
?iif(nr2<nr," Truncating "," Expanding ")+allt(str(abs(nr-nr2)))+" records"
nr2a=mod(nr2,256)
nr2=int(nr2/256)
nr2b=mod(nr2,256)
nr2=int(nr2/256)
nr2c=mod(nr2,256)
nr2d=int(nr2/256)
=fseek(fi,4)
=fwrite(fi,chr(nr2a)+chr(nr2b)+chr(nr2c)+chr(nr2d),4)
endif
else
?"Nothing to fix"
endif
=fclose(fi)
else
??" file not found"
endif
set talk on
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top