2011-12-12 33 views
6

我正在使用舊式Pascal I/O例程,並期望調用失敗的I/O函數應該引發EInOutError。當我嘗試這個時,我沒有看到一個異常提出,我不知道爲什麼。爲什麼I/O錯誤無法引發異常?

procedure TForm1.Button1Click(Sender: TObject); 
//var i: integer; 
begin 
id:=(strtoint(Edit1.Text)-1)*4; 

AssignFile(plik,'\klienci\'+linia_klient[id]+'.txt'); 
try 
Reset(plik); 
except 
    on EInOutError do Rewrite(plik); 
    end; 
edit2.Text:=linia_klient[id+1]; 
edit3.Text:=linia_klient[id+2]; 
//ListBox1.Clear; 
//ListBox1.Items.Add(); 
end; 

整個代碼:

unit Unit1; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, StdCtrls; 

type 
    TForm1 = class(TForm) 
    Label1: TLabel; 
    Edit1: TEdit; 
    Button1: TButton; 
    Label2: TLabel; 
    Label3: TLabel; 
    Edit2: TEdit; 
    Edit3: TEdit; 
    ListBox1: TListBox; 
    Label4: TLabel; 
    procedure FormCreate(Sender: TObject); 
    procedure Button1Click(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    Form1: TForm1; 
    plik:TextFile; 
    linia_klient,linia_video:array[0..20] of string; 
    id:integer; 

implementation 

{$R *.dfm} 
{$IOCHECKS ON} 
procedure TForm1.FormCreate(Sender: TObject); 
var i:integer; 
begin 
Edit1.Text:='Witaj, Podaj ID klienta'; 
Label1.Caption:='ID'; 
AssignFile(plik,'klienci.txt'); 
Reset(plik); 
i:=0; 
While Not Eof(plik) do 
    begin 
    Readln(plik,linia_klient[i]); 
    inc(i); 
    end; 

CloseFile(plik); 
AssignFile(plik,'video.txt'); 
Reset(plik); 
i:=0; 
While Not Eof(plik) do 
    begin 
    Readln(plik,linia_video[i]); 
    inc(i); 
    end; 

CloseFile(plik); 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
//var i: integer; 
begin 
id:=(strtoint(Edit1.Text)-1)*4; 

AssignFile(plik,'\klienci\'+linia_klient[id]+'.txt'); 
try 
Reset(plik); 
except 
    on EInOutError do Rewrite(plik); 
    end; 
edit2.Text:=linia_klient[id+1]; 
edit3.Text:=linia_klient[id+2]; 
//ListBox1.Clear; 
//ListBox1.Items.Add(); 
end; 

end. 

回答

8

的異常,如果I/O檢查是啓用EInOutError纔會得到提升。要確保啓用它做到以下幾點:

  • 在項目的選擇,在 「Delphi編譯器選項」,選中該複選框I/O檢查
  • 刪除任何{$ IOCHECKS OFF}或{$ I - }指令,因爲它們禁用I/O檢查

這應該會給你一個適當的例外,如果該文件不存在。

現在,如果(無論出於何種原因),您不能啓用I/O檢查:

隨着禁用 I/O檢查,如果出現錯誤,你不會得到一個EInOutError。相反,您必須在每次I/O操作後檢查IOResult的值。這就像在舊的帕斯卡爾時代:如果IOResult <> 0那麼發生錯誤。 這(稍作改動)從Delphi docs摘錄顯示瞭如何IOResult工作:

AssignFile(F, FileName); 
    {$I-} 
    Reset(F); 
    {$I+} 
    if IOResult = 0 then 
    begin 
    MessageDlg('File size in bytes: ' + IntToStr(FileSize(F)), 
     mtInformation, [mbOk], 0); 
    CloseFile(F); 
    end 
    else 
    MessageDlg('File access error', mtWarning, [mbOk], 0); 

但是,現在你應該使用TFileStream訪問/創建文件和不再使用的舊風格的Pascal程序。一個例子這怎麼會看:

filename := '\klienci\'+linia_klient[id]+'.txt'; 
if not FileExists(filename) then 
    // "Create a file with the given name. If a file with the given name exists, open the file in write mode." 
    fs := TFileStream.Create(filename, fmCreate) else 
    // "Open the file to modify the current contents rather than replace them." 
    fs := TFileStream.Create(filename, fmOpenReadWrite); 
+0

號看到其爲「異常不工作,我不知道爲什麼。」 –

+0

我編輯過的聲音聽起來不像我建議的那樣。 –

+0

好吧但fmCreate將刪除文件內容。 –

5

我理解你的問題,你想EInOutError例外,每當一個Pascal風格的I/O功能未能得到提升。爲了做到這一點,你需要啓用I/O checking compiler option

I/O檢查:啓用或禁用自動代碼生成,它檢查到一個I/O過程的調用的結果。如果在此開關打開時I/O過程返回非零I/O結果,則會引發EInOutError異常(或者如果未啓用異常處理,程序將終止)。當此開關關閉時,您必須通過調用IOResult來檢查I/O錯誤。

我猜你正在使用的代碼是在I/O檢查選項已啓用的假設下編寫的,但是您正在編譯時未啓用它。以下是一些代碼,說明EInOutError由於I/O錯誤而引發。

program IOchecking; 
{$APPTYPE CONSOLE} 
{$IOCHECKS ON} 
uses 
    SysUtils; 
var 
    F: File; 
begin 
    AssignFile(F, 'path/to/file/that/does/not/exist'); 
    Reset(F);//raises EInOutError 
end. 

我強烈建議您啓用I/O檢查。這將允許您以與您的其他代碼一致的方式處理使用異常的錯誤。

不使用I/O檢查將強制您在每個I/O功能後檢查IOResult的值。這很容易出錯(很容易忘記檢查)並導致代碼不整潔。

如果您已經在我運行/檢查功能Ø然後你沒有看到一個錯誤最可能的解釋是,在事實沒有錯誤發生。也許文件確實存在。

+1

任何人都知道爲什麼這是downvoted。我必須承認,難以理解對這個問題的投票。我誤解了這個問題嗎?我只想知道。 –

+0

+1你可以隨時向我講授大衛。季節的問候。 :-) – Sam

相關問題