2011-12-12 75 views
6

Tôi đang sử dụng các thường trình Pascal I/O kiểu cũ và mong rằng các cuộc gọi đến các hàm I/O không thành công sẽ tăng EInOutError. Khi tôi thử điều này tôi không thấy một ngoại lệ lớn lên và tôi không có lý do tại sao.Tại sao lỗi I/O không thể tăng ngoại lệ?

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; 

Toàn bộ mã:

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. 

Trả lời

8

Ngoại lệ EInOutError sẽ chỉ được nâng lên nếu I/O kiểm tra là kích hoạt. Để chắc chắn rằng nó được kích hoạt làm như sau:

  • Trong tùy chọn dự án của bạn, trong "Delphi Compiler Options" kiểm tra hộp kiểm I/O kiểm tra
  • Hủy bỏ bất kỳ {$ IOCHECKS OFF} hoặc {$ I -} chỉ thị từ mã của bạn khi họ vô hiệu hóa I/O kiểm tra

Điều này sẽ cung cấp cho bạn ngoại lệ thích hợp nếu tệp không tồn tại.

Bây giờ nếu (vì lý do gì), bạn không thể kích hoạt tính năng I/O kiểm tra:

Với tàn tật I/O kiểm tra bạn sẽ không nhận được một EInOutError nếu họ gặp khó khăn. Thay vào đó, bạn phải kiểm tra giá trị của IOResult sau mỗi hoạt động I/O. Nó giống như trong thời gian Pascal cũ: Nếu IOResult <> 0 sau đó một lỗi đã xảy ra. này (hơi thích nghi) đoạn trích từ Delphi docs cho thấy làm thế nào để làm việc với 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); 

Tuy nhiên, ngày nay bạn nên sử dụng TFileStream truy cập/tạo tập tin và không sử dụng các thói quen Pascal phong cách cũ nữa. Một ví dụ như thế nào điều này có thể xem xét:

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

Không. Thấy nó là "ngoại lệ không hoạt động và tôi không biết tại sao". –

+0

Tôi đã chỉnh sửa để làm cho âm thanh ít giống như tôi khuyên bạn nên tắt chúng đi. –

+0

Ok Nhưng fmCreate sẽ xóa nội dung tệp. –

5

tôi giải thích câu hỏi của bạn mà bạn muốn EInOutError trường hợp ngoại lệ được nâng lên bất cứ khi nào một phong cách Pascal I/O chức năng thất bại. Để thực hiện việc này, bạn cần bật số I/O checking compiler option.

Kiểm tra I/O: Bật hoặc tắt tạo mã tự động kiểm tra kết quả cuộc gọi đến thủ tục I/O. Nếu một thủ tục I/O trả về kết quả I/O nonzero khi chuyển đổi này được bật, ngoại lệ EInOutError được nâng lên (hoặc chương trình bị chấm dứt nếu xử lý ngoại lệ không được kích hoạt). Khi công tắc này tắt, bạn phải kiểm tra lỗi I/O bằng cách gọi IOResult.

Tôi đoán mã bạn đang làm việc được viết theo giả định rằng tùy chọn kiểm tra I/O đã được bật, nhưng bạn đang biên dịch với tùy chọn không được bật. Dưới đây là một số mã chứng minh EInOutError được tăng lên do lỗi 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. 

Tôi đặc biệt khuyên bạn nên bật kiểm tra I/O. Điều này sẽ cho phép bạn xử lý lỗi bằng cách sử dụng ngoại lệ theo cách phù hợp với phần còn lại của mã của bạn.

Không sử dụng kiểm tra I/O buộc bạn phải kiểm tra giá trị IOResult sau mỗi chức năng I/O.Điều này là rất dễ bị lỗi (nó dễ dàng để quên kiểm tra) và kết quả trong mã untidy.

Nếu bạn đang chạy với tính năng kiểm tra I/O được bật thì giải thích có khả năng nhất cho bạn không thấy lỗi là trên thực tế không có lỗi xảy ra. Có lẽ tập tin thực tế tồn tại.

+1

Bất cứ ai cũng biết tại sao điều này lại bị giảm giá. Tôi phải thú nhận là có một thời gian khó hiểu sự bỏ phiếu về câu hỏi này. Tôi đã hiểu sai câu hỏi chưa? Tôi chỉ muốn biết. –

+0

+1 bạn có thể thuyết trình tôi vào bất kỳ ngày nào David. Lời chào của mùa. :-) – Sam

Các vấn đề liên quan