天天看點

通過程式設計修複已損壞的表中的問題

 A:如何修複被破壞的VFP表(*.dbf)

----目前在我國,有相當一部分正在運作應用程式是用VFP 編寫的,由于突然斷電、程式非法關閉等原因,經常會導緻VFP資料表.DBF檔案被破壞,如果資料表被破壞了,用VFP打開資料表.DBF時,會出現"notatable/dbf"錯誤提示,導緻無法用VFP打開。

----首先介紹一下VFP資料表.DBF的檔案結構:

----VFP資料表*.DBF的檔案結構由頭記錄和資料記錄組成,頭記錄定義該DBF的結構并包含與該表相關的其它資訊。頭記錄由檔案位置0位元組開始。

----資料表頭部幾個關鍵位元組含義如下:(注:表檔案中存儲整數時低位位元組在前)

----位元組偏移說明

----0 表檔案的版本類型

----1-3 最近更新的日期(YYMMDD)

----4-7 表檔案中記錄的個數

----8-9 第一條記錄的起始位置

----10-11 一條記錄的長度(包括删除标記)

----其它位元組的具體描述不在此贅述,可以參考有關部門書籍或者程式開頭注釋部分。

----在實際工作中發現,許多情況下資料表錯誤都是由于記錄個數比實際記錄個數大1個,以至于資料表無法用打開。

----主要通過以下兩種辦法來對資料表進行修複。

一、用Pctools、urledit、NU的Diskedit等工具軟體進行恢複:

----運作Pctools,選中無法打開的資料表,按E檔案進入編輯功能,按F1切換顯示模式。

----按F3進行編輯,将開始的第5個位元組值減1,按F5存儲,然後退出Pctools,啟動VFP, 發現被破壞的資料表可以打開使用了。

----由于許多操作者并不一定熟悉如何使用Pctools,是以我建議大家可以用比較熟悉的Excel程式根據下面的步驟來進行資料表的恢複。

----用urledit編輯,将開始的第5個位元組值改成另一個正常表檔案相同的值,存儲後退出

二、用Excel進行恢複。

----啟動Excel,選擇"打開"按鈕,出現打開對話框,在打開檔案類型中選擇dBase檔案(*.DBF)檔案類型,再選中被破壞的資料表打開,這時不要做更改,隻選擇"儲存"按鈕,會出現"另存為"對話框,仍選擇以原來檔案名儲存,會提示"檔案已經存在,是否替換已有檔案?",選擇"是"。

----然後選擇"檔案"菜單上的"關閉",會出現提示"資料表檔案不是Excel格式,要保留修改嗎?

----要儲存為Excel格式,單擊'是',然後在'儲存類型'下拉清單框選'Excel工作簿';

----要用現有格式儲存并替換原來的檔案,單擊'是',然後單擊'儲存';

----要在關閉檔案時維持現有格式并不作儲存,單擊'否'。"

----由于我們并沒有對資料表的記錄進行改動,隻是為了恢複資料表,是以選擇最後一項"在關閉檔案時維持現有格式并不作儲存",是以單擊"否",退出Excel。

----啟動VFP,再次打開資料表檔案,發現資料表檔案已可以被打開了,但是觀察資料表的結構,會發現資料表結構中的索引不見了,不過資料表的索引檔案還存在。我們隻需要給資料表Add索引,并選擇原來的索引檔案Open即可。

----添加索引檔案後退出資料表結構設定,并對資料表重新索引一下,就可以繼續使用原 來被破壞的資料表了。

三、如果是VFP6的DBF,那麼用VFP8打開試一試。如果是VFP8的DBF,那麼用VFP6打開試一試

四、如果你的軟體提示“不是DATABASE 資料庫”等意思說明你的資料庫已經受損,需要進行修理。本人在實踐中,摸索出幾種可行的辦法,以供大家參考,如有不正确之處或者其他更好的方法,希望不吝賜教:

    方法1、如果你有Delphi的Database DeskTop,修複DBF檔案是一件非常容易的事,隻要打開損壞的資料庫(用Database DeskTop是可以打開損壞的DBF資料表的),修正損壞的記錄,一般是最後幾條記錄,不能修正的損壞記錄也隻有删除了,然後存盤即可,Database DeskTop的存盤功能會将正确的資料存入資料表中,當然資料表是要重新索引的。

    方法2、使用Excel或Access都可以修複DBF檔案,不過要一些資訊。首先用EXCEL或ACCESS導出正确的資料,将其另存為一個同版本的DBF資料表,再通過修改DBF資料表的字段結構,來修正屬性,最後重建索引,這種方法比較煩瑣,需要的資訊較多,在手頭沒有其他工具時,才可用此方法修複。

    Excel可以直接打開DBF格式的檔案,何不一試?啟動Excel 2000,打開此DBF檔案,竟然沒有任何出錯資訊,内容完好如初,立即以dBase 4資料庫格式存盤,再運作Foxpro,這時,筆者已能用USE指令直接打開資料庫,不過在運作應用程式時出現“資料庫未索引”錯誤資訊,估計用Excel存盤後導緻索引檔案丢失所緻,遂重新索引一遍再試,程式運作正常。

  總結:DBF檔案結構比較簡單,資料庫記錄一般都以文本格式存放,隻是前面加了反映庫結構的檔案頭,是以損壞後也易修複,上述即為一例,我們需要注意兩點:一是存盤格式應為dBase 4的DBF格式,二是原資料庫的索引檔案必須重建。

    方法3、目前網絡上也有許多自稱可以自動修理DBF資料表及其索引的工具,可以試用自動修理工具進行修複。

    Advanced DBF Repair (ACR)是一款強大的修複受損 DBF 檔案的工具,它可以掃描 DBF 檔案并盡可能恢複其中的資料 ,将由資料損壞帶來的損失減至最低.下載下傳位址http://www.fixdown.com/soft/24185.asp

------------------------------------------------------------------------------------------------------------------------------

~~~~~B:恢複無法打開的資料庫檔案(*.dbc)

-----方法一:

執行

VALIDATE DATABASE RECOVER

指令看看有什麼效果,文法如下:

*---------------------------------

保證目前資料庫中表和索引位置的正确性。

Validate Database [RECOVER] [NOCONSOLE]

  [TO PRINTER [PROMPT] | TO FILE FileName]

參數

RECOVER

顯示一個對話框,該對話框允許您定位表和索引,這些表和索引不在被檢查的資料庫中。必須在指令視窗中發出 Validate Database RECOVER 指令,在程式中釋出該指令會産生錯誤資訊。

NOCONSOLE

不向 Visual FoxPro 主視窗或活動的使用者自定義視窗輸出錯誤資訊。

TO PRINTER [PROMPT]

将 VALIDATE DATABASE 指令的錯誤資訊定向輸出到列印機。

PROMPT 在列印前顯示“列印”對話框,該關鍵字應緊跟在 TO PRINTER 之後。

TO FILE FileName

将錯誤資訊定向輸出到由 FileName 參數指定的檔案,如果該檔案已經存在,并且 SET SAFETY 值為 ON,系統會詢問是否要覆寫該檔案。

備注

VALIDATE DATABASE 指令確定資料庫包含的表和索引處于正确位置,確定資料庫中的表包含正确的字段,以及确定資料庫中索引辨別是否存在。

VALIDATE DATABASE 指令在目前資料庫上操作。在釋出 OPEN DATABASE 指令打開此資料庫時,必須包含 EXCLUSIVE 關鍵字,以獨占方式打開。

示例

下面的示例打開 testdata 資料庫并使用 VALIDATE DATABASE 指令,以确定表和索引的位置在資料庫中是正确的。

CLOSE DATABASES

SET PATH TO (HOME(2) + 'Data\') && 設定資料庫路徑

OPEN DATABASE testdata EXCLUSIVE && 打開 testdata 資料庫

Validate Database

*------------------------------

如果還是不行,

就隻好:

1、删除dbc檔案

2、去掉所有dbf檔案對資料庫的引用

3、再建立一個dbc

4、然後加入所有dbf檔案

------方法二:

    在使用VFP資料庫軟體時,有時會發生資料庫檔案無法打開的錯誤,如:(1) not a database file(不是資料庫檔案) 。(2) memo file is missing/invalid(備注檔案丢失/無效)等。若無法打開的資料庫檔案不能恢複,将給使用者帶來損失。那麼如何恢複無法打開的資料庫檔案呢?首先須清楚資料庫檔案的結構。VFP中的資料庫檔案由檔案描述部分和檔案的資料内容兩部分組成。檔案的描述部分在檔案前部,描述部分結束後是檔案中存儲的資料記錄。檔案描述又分成兩部分:檔案的整體結構的描述和每個字段的描述。整體結構描述由檔案的第一個位元組開始,共需32個位元組。其中:

  第1位元組:備注檔案标志位;

  第2~4位元組:檔案的最後修改日期(年,月,日);

  第5~8位元組:檔案記錄數,低位在前高位在後;

  第9~10位元組:資料計錄内容存儲的開始位置,即字段描述結束後的下一個位元組位置,低位在前高位在後;

  第11~12位元組:記錄長度(全部字段長之和),低位在前高位在後;

  第29位元組:組合索引檔案存在标記。

  從第33個位元組開始,每32個位元組描述一個字段。

  第1位元組為“f5”表示資料庫檔案應有備注檔案,若無備注檔案欲打開該資料庫檔案就會出現本文開頭的錯誤資訊(2),此時隻須将“f5”改成“03”即可(用pctool),“03”表示資料庫檔案無備注檔案。

  第29位元組為“01”,表示資料庫檔案打開的同時打開組合索引檔案。若無組合索引檔案,也會出現錯誤提示資訊,将“01”改成“00”即可,“00”表示資料庫檔案無組合索引檔案。

  欲打開資料庫檔案,螢幕報告“not a database file”(不是資料庫檔案)錯誤,是由于第5~8位元組表示的檔案記錄數大于資料庫檔案實際記錄數(若小于等于資料庫檔案實際記錄數則不會報告錯誤),此時恢複該資料庫檔案隻要獲得檔案的實際記錄數,用手工方法修改檔案的第5~8位元組。資料庫檔案實際記錄數可以通過下面的公式計算:

  記錄數=(檔案長度-檔案描述部分長度-檔案結束标志長度)/記錄長度式中,檔案長度可通過“dir”指令獲得;

  檔案描述部分長度=(第10位元組)10 *256+(第9位元組)10 ;

  檔案結束标志長度=1;

  記錄長度=(第12位元組)10 *256+(第11位元組)10;

  若是資料庫檔案上述公式一定能整除,由公式計算出的記錄數再換算成16進制填入檔案的第5~8位元組,注意低位在前高位在後。

  根據上述過程筆者用c語言編寫了恢複該資料庫檔案的程式modi.cpp(該程式在bc31 for dos下編譯通過):

  #include 

  #include 

  #include 

  int main(int argc,char *argv[])

  {

   file *fp;

   unsigned int c[4],i;

   long int total,records;

   if(argc!=2){

   printf("no file name!\n");

    exit(1);

  }

   if( (fp=fopen(argv[1],"r+b"))==null){

   printf("not find %s!\n",argv[1]);

   exit(1);

   }

   total=filelength(fileno(fp));//獲得檔案長度

   rewind(fp);

   i=fgetc(fp); //讀取第1個位元組的值

   if (i!=0xf3&&i!=0x03){

   fseek(fp,-1l,1);

   fputc(0x03,fp); //第1個位元組的值若不為“f3”或“03”

   } //則強迫為“03”

   rewind(fp);

   fseek(fp,8l,1); //指針指向第9位元組

   c[0]=fgetc(fp); //讀取第9~12位元組的值

   c[1]=fgetc(fp);

   c[2]=fgetc(fp);

   c[3]=fgetc(fp);

   records=(total-c[1]*256+c[0]-1)/(c[2]+c[3]*256);//計算記錄數

   c[0]=records%256; //c[0]~c[3]計算第5~8位元組的值

   c[1]=(records-c[3]*256*256*256-c[2]*256*256)/256;

   c[2]=(records-c[3]*256*256*256)/65536;

   c[3]=records/256/256/256;

   fseek(fp,-8l,1); //指針指向第5位元組

   fputc(c[0],fp); //将c[0]~c[3]寫入第5~8位元組

   fputc(c[1],fp);

   fputc(c[2],fp);

   fputc(c[3],fp);

   printf("modify the database file successfully!\n");

   fclose(fp);

   return 1;

--------方法三:

  将所有的dbf,cdx,dbc檔案都删除了。然後用它們的備分檔案件,bak,dcx,bdc分别改名,然後,在項目裡打開資料庫,将裡面的所有表移除,删除資料庫,再新建立資料庫,再将表加入。