为什么 I/O 错误无法引发异常?
我正在使用旧式 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'm using old style Pascal I/O routines and expect that calls to I/O functions that fail should raise an EInOutError
. When I try this I do not see an exception raised and I have no clue why.
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;
Entire code:
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

发布评论
评论(2)
我将您的问题解释为您希望在 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 检查的情况下运行,那么您没有看到错误的最可能的解释是实际上没有发生错误。也许该文件确实存在。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
仅当启用 I/O 检查时才会引发异常
EInOutError
。要确保它已启用,请执行以下操作:如果文件不存在,这应该会给你一个适当的异常。
现在,如果(无论出于何种原因)您无法启用 I/O 检查:
通过禁用 I/O 检查,如果出现问题,您将不会收到
EInOutError
错误。相反,您必须在每次之后检查 IOResult 的值输入/输出操作。就像在旧的 Pascal 时代: If IOResult <> 0 然后发生错误。这段摘自 Delphi 文档 的摘录(稍作修改)展示了如何使用 IOResult:
但是,现在您应该使用
TFileStream
访问/创建文件,不再使用旧式 Pascal 例程。一个例子:The exception
EInOutError
will only be raised if I/O checking is enabled. To make sure it is enabled do the following:This should give you a proper exception if the file doesn't exist.
Now if (for whatever reason) you cannot enable I/O checking:
With disabled I/O checking you won't get an
EInOutError
if something goes wrong. Instead you have to check the value of IOResult after every I/O operation. It's like in old Pascal times: IfIOResult <> 0
then an error happened.This (slightly adapted) excerpt from the Delphi docs shows how to work with IOResult:
However, nowadays you should use
TFileStream
to access/create files and don't use the old style Pascal routines anymore. An example how this could look: