使用TIdftp控件,出现错误:error message:list index out of bounds(0) ( 积分: 100 )

  • 主题发起人 主题发起人 superdba
  • 开始时间 开始时间
S

superdba

Unregistered / Unconfirmed
GUEST, unregistred user!
开发环境:windows 2000 个人版
开发工具:delphi 2005
以下程序原来[red]在delphi 7下开发调试通过(使用indy9),运行正常,[/red]但把相同程序[red]在delphi 2005下以win32程序方式打开并调试(使用indy10),则出现错误提示[/red]:error message:list index out of bounds(0)
由于在以下的 if IdFTP1.DirectoryListing.Items[FileCount].ItemType = ditDirectory then
这行程序提示index out of bounds(0)出错,我分析可能directorylisting.items并没有获取到任何集合元素?所以访问集合内元素报出界,但不知道具体出错原因在哪里,如何解决,请大家指点迷津,谢谢!

procedure TfrmFtpClient.ChageDir(DirName: String);
Var
LS: TStringList;
FileCount,total : Integer;
newItem : TListItem;
begin
//延时半秒
DelayTime(GTick);
LS := TStringList.Create;
try
try
Idftp1.ChangeDir(DirName);
except
//IdFTP1.Quit;

//注释掉,Michael,20050429----
{IdFTP1.Connect(true);
IdFTP1.ChangeDir(DirName);
}
//---------------------------

end;
// IdFTP1.TransferType := ftASCII;

//延时半秒
DelayTime(GTick);
try
//gCurrentDir:=CurrentDirEdit.Text;
IdFTP1.List(LS,'*',False);
//延时半秒
DelayTime(GTick);
//CurrentDirEdit.Text:= IdFTP1.RetrieveCurrentDir;
CurrentDirEdit.Text:= DirName;

except
on e:exception do
geterrmsg(e);
end;
//延时半秒
DelayTime(GTick);

ListViewRemoteFile.Items.BeginUpdate;
ListViewRemoteFile.Items.Clear;
//IdFTP1.DirectoryListing.ListFormat:=flfUnix;
total:=LS.Count - 1;

for FileCount:=0 to total do
begin
//是目录吗?
[red]if IdFTP1.DirectoryListing.Items[FileCount].ItemType = ditDirectory then[/red]
//在上行提示index out of bounds(0)出错
begin
//添加目录项目
newItem := ListViewRemoteFile.Items.Insert(0);
newItem.ImageIndex := 0; //图标序号
newItem.subItems.Add('文件夹');
end else
begin
//添加文件项目
newItem := ListViewRemoteFile.Items.Add;
newItem.ImageIndex := 1; //图标序号
newItem.subItems.Add('文件');
end ;
newItem.Caption := IdFTP1.DirectoryListing.Items[FileCount].FileName; //文件名
newItem.subItems.Add(IntToStr(IdFTP1.DirectoryListing.Items[FileCount].Size)); //文件大小
newItem.subItems.Add(DateTimeToStr(IdFTP1.DirectoryListing.Items[FileCount].ModifiedDate)); //时间
end;
ListViewRemoteFile.Items.EndUpdate;
finally
LS.Free;
end;
end;
 
开发环境:windows 2000 个人版
开发工具:delphi 2005
以下程序原来[red]在delphi 7下开发调试通过(使用indy9),运行正常,[/red]但把相同程序[red]在delphi 2005下以win32程序方式打开并调试(使用indy10),则出现错误提示[/red]:error message:list index out of bounds(0)
由于在以下的 if IdFTP1.DirectoryListing.Items[FileCount].ItemType = ditDirectory then
这行程序提示index out of bounds(0)出错,我分析可能directorylisting.items并没有获取到任何集合元素?所以访问集合内元素报出界,但不知道具体出错原因在哪里,如何解决,请大家指点迷津,谢谢!

procedure TfrmFtpClient.ChageDir(DirName: String);
Var
LS: TStringList;
FileCount,total : Integer;
newItem : TListItem;
begin
//延时半秒
DelayTime(GTick);
LS := TStringList.Create;
try
try
Idftp1.ChangeDir(DirName);
except
//IdFTP1.Quit;

//注释掉,Michael,20050429----
{IdFTP1.Connect(true);
IdFTP1.ChangeDir(DirName);
}
//---------------------------

end;
// IdFTP1.TransferType := ftASCII;

//延时半秒
DelayTime(GTick);
try
//gCurrentDir:=CurrentDirEdit.Text;
IdFTP1.List(LS,'*',False);
//延时半秒
DelayTime(GTick);
//CurrentDirEdit.Text:= IdFTP1.RetrieveCurrentDir;
CurrentDirEdit.Text:= DirName;

except
on e:exception do
geterrmsg(e);
end;
//延时半秒
DelayTime(GTick);

ListViewRemoteFile.Items.BeginUpdate;
ListViewRemoteFile.Items.Clear;
//IdFTP1.DirectoryListing.ListFormat:=flfUnix;
total:=LS.Count - 1;

for FileCount:=0 to total do
begin
//是目录吗?
[red]if IdFTP1.DirectoryListing.Items[FileCount].ItemType = ditDirectory then[/red]
//在上行提示index out of bounds(0)出错
begin
//添加目录项目
newItem := ListViewRemoteFile.Items.Insert(0);
newItem.ImageIndex := 0; //图标序号
newItem.subItems.Add('文件夹');
end else
begin
//添加文件项目
newItem := ListViewRemoteFile.Items.Add;
newItem.ImageIndex := 1; //图标序号
newItem.subItems.Add('文件');
end ;
newItem.Caption := IdFTP1.DirectoryListing.Items[FileCount].FileName; //文件名
newItem.subItems.Add(IntToStr(IdFTP1.DirectoryListing.Items[FileCount].Size)); //文件大小
newItem.subItems.Add(DateTimeToStr(IdFTP1.DirectoryListing.Items[FileCount].ModifiedDate)); //时间
end;
ListViewRemoteFile.Items.EndUpdate;
finally
LS.Free;
end;
end;
 
total:=LS.Count - 1;
换成
total:=IdFTP1.DirectoryListing.Items.count
试试
 
支持楼上,

另外觉得应该 -1
total:=IdFTP1.DirectoryListing.Items.count-1
 
数组越界啊!
仔细查看一下,那里越界了!
 
错误显而易见:
1、TIdFTP.List 方法的第三个参数设为 'False' 那么 List 只列出文件名,而不罗列出文件大小、类型等信息,越界的错误就从这而来;
2、把 TIdFTP.List 的第二个参数设为 '*' 表示只列出文件夹,你在后面对 ItemType 的判断又有何用;
3、把 idFTP1 的文件列表读入 ls 也是多此一举,不过你愿意的话也可以;
4、这么多错误,不报错才怪。改正如下:
idFTP1.List(LS, '*', False)—>idFTP1.List(nil, '', True)...
for FileCount:=0 to total do—>for FileCount := 0 to idFTP1.DirectoryListing.Count - 1 do...
5、OK 乎?给个话乎?
 
不好意思,我不知道如何进入回复界面编辑回复消息,所以只能在问题的注释空间填写以下回复信息:
首先感谢ak_2004,ibmos_2,vvyang无泪的热心相助。
到目前,vvyang的方法最详细,我试了该方法,idFTP1.DirectoryListing.Count的值为0,所以仍然报告出界错误,是不是indy9到indy10修改了ftp的list方法和directorylisting 属性引起的问题,希望有过在indy10上使用和directorylisting 属性的朋友指点迷津,本人感激不尽!
 
To superdba:
1、如果 idFTP1.DirectoryListing.Count = 0,那么循环体根本就不会被执行,越界错误又从何而来,开玩笑吧?
2、你把改过之后的代码贴上来吧。
 
[red]改后的代码:[/red] //延时半秒
DelayTime(GTick);
try
//gCurrentDir:=CurrentDirEdit.Text;
IdFTP1.List(LS,'',True);

//延时半秒
DelayTime(GTick);
CurrentDirEdit.Text:= IdFTP1.RetrieveCurrentDir;

except
on e:exception do
geterrmsg(e);
end;
//延时半秒
DelayTime(GTick);

ListViewRemoteFile.Items.BeginUpdate;
ListViewRemoteFile.Items.Clear;
//IdFTP1.DirectoryListing.ListFormat:=flfUnix;
//for FileCount:=0 to LS.Count - 1 do
for FileCount:=0 to IdFTP1.DirectoryListing.Count - 1 do
begin
//是目录吗?
if IdFTP1.DirectoryListing.Items[FileCount].ItemType = ditDirectory then
begin
//添加目录项目
newItem := ListViewRemoteFile.Items.Insert(0);
newItem.ImageIndex := 0; //图标序号
newItem.subItems.Add('文件夹');
end else
begin
//添加文件项目
newItem := ListViewRemoteFile.Items.Add;
newItem.ImageIndex := 1; //图标序号
newItem.subItems.Add('文件');
end ;
newItem.Caption := IdFTP1.DirectoryListing.Items[FileCount].FileName; //文件名
newItem.subItems.Add(IntToStr(IdFTP1.DirectoryListing.Items[FileCount].Size)); //文件大小
newItem.subItems.Add(DateTimeToStr(IdFTP1.DirectoryListing.Items[FileCount].ModifiedDate)); //时间
end;
ListViewRemoteFile.Items.EndUpdate;
finally
LS.Free;
end;
[red]不好意思,顺便纠正一个前面的表述错误,没有报告出界错误,而是directorylisting无返回。[/red]
 
1、你这段代码基本没什么问题了,DelayTime 是干吗用的;
2、你看看你的 ftp 目录中有没有文件,问题不在 indy10 上,你的代码很可能还有问题;
3、你把我写的这段贴到程序里看看行不行。
procedure TfrmFtpClient.ChageDir(DirName: String);
var
FileCount: Integer;
newItem: TListItem;
begin
//延时半秒
DelayTime(GTick);
idFTP1.TransferType := ftASCII;
try
Idftp1.ChangeDir(DirName);
except
end;

DelayTime(GTick);
try
IdFTP1.List(nil, '', True);
//延时半秒
DelayTime(GTick);
CurrentDirEdit.Text := IdFTP1.RetrieveCurrentDir;
except
on e:exception do
geterrmsg(e);
end;
//延时半秒
DelayTime(GTick);
ListViewRemoteFile.Items.BeginUpdate;
ListViewRemoteFile.Items.Clear;
for FileCount := 0 to IdFTP1.DirectoryListing.Count - 1 do
begin
//是目录吗?
if IdFTP1.DirectoryListing.Items[FileCount].ItemType = ditDirectory then
begin
//添加目录项目
newItem := ListViewRemoteFile.Items.Insert(0);
newItem.ImageIndex := 0; //图标序号
newItem.subItems.Add('文件夹');
end
else begin
//添加文件项目
newItem := ListViewRemoteFile.Items.Add;
newItem.ImageIndex := 1; //图标序号
newItem.subItems.Add('文件');
end ;
newItem.Caption := IdFTP1.DirectoryListing.Items[FileCount].FileName; //文件名
newItem.subItems.Add(IntToStr(IdFTP1.DirectoryListing.Items[FileCount].Size)); //文件大小
newItem.subItems.Add(DateTimeToStr(IdFTP1.DirectoryListing.Items[FileCount].ModifiedDate)); //时间
end;
ListViewRemoteFile.Items.EndUpdate;
end;
 
to vvyang:
目录下有文件和目录的,还是不行!我单独做了一个ftp的例子,list一下然后去取directorylisting属性,也是没有返回,你可以去试一下,可能确实与indy10有关。
 
今天碰巧在国外一个网站上看到以下的问题,经过试验,只要在uses语句中加入单元IdFTPListParseUnix(注:我用的是linux的vsftp),终于解决了问题。
[red]TIdFTP.DirectoryListing is returning nothing for my FTP server. Why? [/red]

We restructured the way FTP directory listing is done. The code is now a plug in system with various parsers in their own units which register themselves into a framework. To add support for a particular type of FTP server, you simply add the parser unit to one of your program unit's uses clause.

To add the Unix directory list parser, add IdFTPListParseUnix to your unit's clause. To add support for Microsoft Windows NT IIS FTP server, add IdFTPListParseWindowsNT to your uses clause. You can also add many other parsers we include in the Indy packages. By convention, they are named IdFTPListParser followed by the server type. You do not need to add IdFTPListParseBase to your uses clause because IdFTP uses that unit. If you wish to use all of Indy's FTP List parser classes, just add the IdAllFTPListParsers unit to your uses clause.

We admit this new design is not as intuitive as the older one but this has many advantages for us such as:

· The FTP list parsing code is now much easier to maintain than the same code in a non-modular design in one unit which would be at least 150KB total.

· You now can add support for only the FTP servers you want your program support to support.

· You can now write your own custom parser classes and plug those into the standard FTP parsing list framework.
 
indy10的许多用法还不太熟悉,只有熟悉了这些控件的正确用法,才不会出问题,再次向各位表示感谢!
 
你跟无泪是亲戚么?呵呵。
 
不好意思,分数给错了
 
后退
顶部