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

Is there a way to solve an I/O error 6 in Delphi?

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 error 6' 错误并且没有任何显示。不知道是文本文件的问题还是显示程序的问题

您的代码存在一些问题,但具体针对 I/O 错误,错误 6 表示 "invalid file handle"。

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

I/O 错误 6 不是典型的 System.Reset(), and you are not seeing any other kind of error related to a failure in opening a file, so we can safely assume that the file is being opened successfully, and that System.Readln() and System.CloseFile() 失败 未传递无效的 I/O 句柄。

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

while not EOF do

System.Eof() has an optional parameter to tell it which file to check. Since you are omitting that parameter, Eof() will use System.Input 代替。并且 GUI 进程没有默认分配的 STDIN 句柄。所以这很可能是错误 6 的来源。

该行需要改为:

while not EOF(tSongFile) do

UPDATE:鉴于您在评论 (arrSongs: array[1..MAX] of string;) 中显示的 arrSongs 声明,您的代码还有其他问题。您需要确保读取循环不会尝试在数组中存储超过 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;