有没有办法解决Delphi中的I / O错误6?

时间:2020-03-12 13:49:08

标签: delphi delphi-xe2 delphi-xe

procedure TfrmSongs.Display;
var
  i: Integer;
begin
  redOutput.Clear;
  redOutput.Lines.Add('The TOP 10');
  for i := 1 to iCount-1 do
  begin
    redOutput.Lines.Add(IntToStr(i)+arrSongs[i]);
  end;
end;

procedure TfrmSongs.FormActivate(Sender: TObject);
var
  tSongList: TextFile;
  sSong: string;
begin
  iCount := 0;
  AssignFile(tSongList, ExtractFilePath(Application.ExeName)+'Songs.txt');
  Reset(tSongList);
  while not EOF do
  begin
    Readln(tSongList, sSong);
    arrSongs[iCount] := sSong;
    Inc(iCount);
  end;
  CloseFile(tSongList);
  Display;
end;

我正在尝试通过富文本编辑显示通过文本文件创建的数组。但是,每次我运行该应用程序时,都会显示“ I / O错误6”错误,并且没有任何显示。我不知道这与文本文件有关,还是与显示过程有关。

1 个答案:

答案 0 :(得分:5)

您的代码有一些问题,但是关于I / O错误,错误6表示“无效的文件句柄”。

由于收到弹出错误通知,因此您显然已启用I/O checking,这是默认设置。

I / O错误6并不是System.Reset()上失败的典型代表,并且您没有看到与打开文件失败有关的任何其他类型的错误,因此我们可以放心地假设该文件正在已成功打开,并且没有向System.Readln()System.CloseFile()传递无效的I / O句柄。

所以只剩下一行可能接收到无效的I / O句柄:

while not EOF do

System.Eof()有一个可选参数来告诉它要检查哪个文件。由于您省略了该参数,因此Eof()将使用System.Input。并且GUI进程没有默认分配的STDIN句柄。所以这很可能是错误6的来源。

该行需要改为:

while not EOF(tSongFile) do

更新:鉴于已在注释(arrSongs)中显示了arrSongs: array[1..MAX] of string;的声明,因此代码还有其他问题。您需要确保读取循环不会尝试在数组中存储超过MAX个字符串。另外,您的读取循环正在尝试将一个字符串存储在索引0处,该索引不是有效的索引,因为该数组从索引1开始。而且,Display()跳过了字符串中的 last 字符串。数组。看到省略重要细节会发生什么?

尝试以下方法:

private
  arrSongs: array[1..MAX] of string;

...

procedure TfrmSongs.Display;
var
  i: Integer;
begin
  redOutput.Clear;
  redOutput.Lines.Add('The TOP 10');
  for i := 1 to iCount do
  begin
    redOutput.Lines.Add(IntToStr(i) + arrSongs[i]);
  end;
end;

procedure TfrmSongs.FormActivate(Sender: TObject);
var
  tSongList: TextFile;
  sSong: string;
begin
  iCount := 0;
  AssignFile(tSongList, ExtractFilePath(Application.ExeName) + 'Songs.txt');
  Reset(tSongList);
  try
    while (not EOF(tSongList)) and (iCount < MAX) do
    begin
      Readln(tSongList, sSong);
      arrSongs[1+iCount] := sSong;
      Inc(iCount);
    end;
  finally
    CloseFile(tSongList);
  end;
  Display;
end;

话虽如此,我建议您完全摆脱阅读循环。您可以改用TStringList

uses
  ..., System.Classes;

...

private
  lstSongs: TStringList;

...

procedure TfrmSongs.Display;
var
  i: Integer;
begin
  redOutput.Clear;
  redOutput.Lines.Add('The TOP 10');
  for i := 0 to lstSongs.Count-1 do
  begin
    redOutput.Lines.Add(IntToStr(i+1) + lstSongs[i]);
  end;
end;

procedure TfrmSongs.FormCreate(Sender: TObject);
begin
  lstSongs := TStringList.Create;
end;

procedure TfrmSongs.FormDestroy(Sender: TObject);
begin
  lstSongs.Free;
end;

procedure TfrmSongs.FormActivate(Sender: TObject);
begin
  lstSongs.LoadFromFile(ExtractFilePath(Application.ExeName) + 'Songs.txt');
  Display;
end;

或者,您可以改用TFile.ReadAllLines()

uses
  ..., System.IOUtils;

...

private
  arrSongs: TStringDynArray;

...

procedure TfrmSongs.Display;
var
  i: Integer;
begin
  redOutput.Clear;
  redOutput.Lines.Add('The TOP 10');
  for i := 0 to High(arrSongs) do
  begin
    redOutput.Lines.Add(IntToStr(i+1) + arrSongs[i]);
  end;
end;

procedure TfrmSongs.FormActivate(Sender: TObject);
begin
  arrSongs := TFile.ReadAllLines(ExtractFilePath(Application.ExeName) + 'Songs.txt');
  Display;
end;