[英]Why do I/O errors fail to raise exceptions?
我正在使用旧式Pascal I / O例程,并期望对失败的I / O函数的调用会引发EInOutError
。 当我尝试这个时,我没有看到异常提出,我不知道为什么。
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.
只有在启用 I / O检查时才会引发异常EInOutError
。 要确保它已启用,请执行以下操作:
如果文件不存在,这应该给你一个适当的例外。
现在,如果(无论出于何种原因)您无法启用I / O检查:
使用禁用的 I / O检查,如果出现问题,您将无法获得EInOutError
。 相反,您必须在每次I / O操作后检查IOResult的值。 这就像旧帕斯卡时代一样:如果IOResult <> 0
则发生错误。 Delphi文档中的这个(略微改编)摘录展示了如何使用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);
我解释你的问题,你希望每当Pascal样式I / O函数失败时都会引发EInOutError
异常。 为此,您需要启用I / O检查编译器选项 。
I / O检查 :启用或禁用自动代码生成,以检查对I / O过程的调用结果。 如果在此开关打开时I / O过程返回非零I / O结果,则会引发EInOutError异常(或者如果未启用异常处理,程序将终止)。 当此开关关闭时,您必须通过调用IOResult来检查I / O错误。
我猜你正在使用的代码是在假设I / O检查选项已启用的情况下编写的,但是您正在编译它未启用它。 这里有一些代码可以演示由于I / O错误引发的EInOutError
。
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
的值。 这非常容易出错(很容易忘记检查)并导致代码不整齐。
如果您已经在启用了I / O检查的情况下运行,那么最可能的解释是您没有看到错误,实际上没有发生错误。 也许该文件确实存在。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.