FTP服务的LIST指令获取的文件列表信息的解析

原创 2005年05月16日 17:44:00

客户端使用LIST命令指定获取服务器端FTP共享目录(或者下面的子目录),服务器端将通过数据端口将该指定目录下的文件列表(包括子目录)信息发送给客户端。本文对该文件列表信息进行分析和解析。

文件列表信息分为UNIX格式和DOS格式两种。笔者是比照了Serv-U和微软自带的FTP服务器写出本文的,也许别的服务器另有新的方式或者格式也说不定,欢迎大家补充。

首先不妨来看一下UNIX格式和DOS格式下的文件列表信息都是怎么样的:

 //MS-DOS文件列表格式解析
 //02-23-05  09:24AM                 2245 readme.ESn
 //05-25-04  08:56AM             19041660 VC.ESn


  UNIX文件列表格式解析
  UNIX文件格式:
  Serv-U:
  -rwxrw-r--   1 user     group        3014 Nov 12 14:57 cwinvnc337.ESn
  -rwxrw-r--   1 user     group       20480 Mar  3 11:25 inmcsvr更新说明.ESn
  -rwxrw-r--   1 user     group         450 Apr 13 11:39 对话框中加入工具条.ESn
  Windows自带FTP:
  -rwxrwxrwx   1 owner    group        19041660 May 25  2004 VC.ESn
  -rwxrwxrwx   1 owner    group             450 Apr  6 15:04 对话框中加入工具条.ESn

注:由于未发现Serv-U支持DOS格式,因此DOS格式只列了微软自带的。

下面我们对以上的格式进行分析:

首先,文件列表信息中,每个文件的信息之间用回车换行符(/r/n)分隔。因此分解时第一步就是用/r/n进行截取。然后是对每一个文件信息的解析。

每一个文件信息中,分为多个信息段,各个信息段之间用一个空格符间隔。UNIX格式和DOS格式的信息段的数量的顺序是不同的。下面将分别分析。

先看看DOS格式,拿出一条文件信息来讲:02-23-05  09:24AM                 2245 readme.ESn


第一段为05-25-04,一个空格后,为第二段08:56AM,一个空格后,为    19041660,由于文件长度不一定,预留的位置比较长,因此前面用空格填充了。
解析的时候,逐段用空格截取,记住,截取完第一段后,剩下的内容先用TrimLeft去除左侧的空格,然后继续截取就可以了。
因此,DOS格式共分四段,其中第一段为日期,第二段为时间,第三段为文件长度,第四段为文件名称。

对了,如果只需要获取文件名称,你也不能从后面截取,因为文件名称是允许带空格的。:》
另外,如果列举的是个目录,那么,第三段就不是文件长度了,而是固定为:<DIR>


再看UNIX格式,也拿出一条文件信息来讲:
-rwxrw-r--   1 user     group        3014 Nov 12 14:57 cwinvnc337.ESn
unix我不熟,每一段的意义不太清楚。但以上的格式分解为:第一段为-rwxrw-r--,第二段为1,第三段为user,第四段为group,第五段为文件长度,第六段为月,第七段为日,第八段为时间,第九段为文件名称。
需要注意的是:如果格式串的第一个字符为d,表示为一个目录信息,比如drwxrw-r--
另外,第八段有可能不是时间,而是年份,比如2005,从上面的例子中你可以发现。


对于不同的FTP服务器,LIST获取的信息不尽相同,但段的顺序和意义是不变的。只是表示文件的长度的段的长度有所不同。
以下是笔者在实际项目中的解析函数,做的不是很好,但希望对大家有所帮助吧。

/***************************************************
 Function:  CRecvFileMan::PraseFileList_MSDOS
 Description: 解析MSDOS风格的文件列表
 Table Accessed: 
 Table Updated: 
 Parameter:  CString sFileList - MSDOS风格文件列表
 Return:   无返回值
 Others:   
***************************************************/
void CRecvFileMan::PraseFileList_MSDOS(CString sFileList)
{
 CString sLen;
 CString sFile;
 CString sOneFile;
 int nIdx = 0;
 while(1)
 {
  nIdx = sFileList.Find("/r/n");
  if(nIdx == -1)
   break;
  sOneFile = sFileList.Left(nIdx);
  sFileList = sFileList.Mid(nIdx + 2);
  sLen = GetSegmentInfo(sOneFile,2);
  if(sLen == "<DIR>")
  {
   continue;
  }
  sFile = GetSegmentInfo(sOneFile,0);
  //根据解析的文件信息,形成下载文件类对象
  CRecvFile *pFile = new CRecvFile(sFile,atoi(sLen));
   m_arTransFile.Add(pFile);
 };
}

/***************************************************
 Function:  CRecvFileMan::PraseFileList_UNIX
 Description: 解析UNIX风格的文件列表
 Table Accessed: 
 Table Updated: 
 Parameter:  CString sFileList - UNIX风格文件列表,以回车换行分隔
 Return:   无返回值
 Others:   
***************************************************/
void CRecvFileMan::PraseFileList_UNIX(CString sFileList)
{
 CString sLen;
 CString sFile;
 CString sOneFile;
 int nIdx = 0;
 while(1)
 {
  nIdx = sFileList.Find("/r/n");
  if(nIdx == -1)
   break;
  sOneFile = sFileList.Left(nIdx);
  sFileList = sFileList.Mid(nIdx + 2);
  if(sOneFile.GetAt(0) == 'd')//第一个字母是d,表示是目录,忽略
   continue;
  sLen = GetSegmentInfo(sOneFile,4);
  sFile = GetSegmentInfo(sOneFile,3);
  //根据解析的文件信息,形成下载文件类对象
   CRecvFile *pFile = new CRecvFile(sFile,atoi(sLen));
   m_arTransFile.Add(pFile);
 };
}

/***************************************************
 Function:  CRecvFileMan::GetSegmentInfo
 Description: 得到文件列表中某个文件描述的指定段的信息
 Table Accessed: 
 Table Updated: 
 Parameter:  CString &sFileInfo - 指定的文件描述信息。即是传入,也是传出参数
           将获取段号信息后剩余的信息返回,以便进一步截取其它信息
     int nSegment - 指定的段号,从0开始
 Return:   CString - 指定段号的信息
 Others:   
***************************************************/
CString CRecvFileMan::GetSegmentInfo(CString &sFileInfo,int nSegment)
{
 int nIdx = -1;
 int nSeg = 0;
 CString sInfo = "";
 sFileInfo.TrimLeft();
 while(nSeg < nSegment + 1)//逐段切隔
 {
  nIdx = sFileInfo.Find(" ");//以空格为切隔
  if(nIdx < 0)//如果已没有空格,即最后一段信息
  {
   if(nSeg == nSegment)//如果最后一段正好是需要的段
   {
    sInfo = sFileInfo;//返回剩余信息
   }
   else
    sInfo = "";
   break;
  }
  else
  {
   sInfo = sFileInfo.Left(nIdx);//得到段信息
   sFileInfo = sFileInfo.Mid(nIdx+1);//切隔信息
   sFileInfo.TrimLeft();//过滤左侧的空格符
  }
  nSeg++;
 }
 return sInfo;
}

解析FTP的LIST命令发回的数据

FTP的“LIST”命令用来获得FTP上指定目录下的文件列表信息,Windows下FileZilla服务器发回的文件列表信息格式如下: drwxr-xr-x 1 ftp ftp            ...

FTP服务器LIST指令获取的文件列表信息解析(UNIX格式)

最近在写FTP客户端的程序,但是在发送LIST指令之后,不知如何解析服务器发回的列表信息,上网一查,略坑,居然都是同一篇文章,居然还都是原创,而且对于UNIX格式下的文件列表信息并没有解析完成,因为没...

FTP命令详解(含操作实例)

以下是微软命令行FTP客户端命令大全,如果你想使用“未加工(RAW)”FTP命令而非下面翻译过的请参考:http://www.nsftools.com/tips/RawFTP.htm   操作实例...
  • IndexMan
  • IndexMan
  • 2015年06月06日 13:17
  • 53195

FTP命令:LIST

LIST命令用于列出指定目录中的子目录和文件信息,如果没有指定目录的名字就默认列出当前目录下的所有子目录和文件信息并返回给客户端。--如果路径名指定的是一个目录名,服务器会发送一份指定目录中的子目录和...
  • yhtppp
  • yhtppp
  • 2010年07月04日 11:37
  • 5952

FTP协议(指令集)

FTP协议采用一系列简单的协议来完成文件传输的各种任务,在发送命令的时候,总是在命令的最后加上一个回车换行符,在VB中可以用“vbcrlf”来实现,vc中以“/r/n”表示。以下的命令是从Postel...

获取ftp服务器文件和目录列表

转载地址:http://www.cnblogs.com/zgshi/archive/2011/11/17/2252533.html 下面只是我从转载地址提取的自己需要的部分,加了一下自己的变...

C# 遍历FTP文件夹/下载

原文链接:http://blog.csdn.net/ou8811/article/details/5295780 整个程序大致可以分为2个部分,第一部分是实现单个文件下载的方法  ...

C#获取远程FTP文件列表

FtpWebRequest request; try { request = (FtpWebRequest)FtpWebRequest.Create(new Uri(FTPUrl));//FTP...
  • hhl2046
  • hhl2046
  • 2015年05月29日 15:28
  • 1162

c# 使用FtpWebRequest,FtpWebResponse ,Stream 实现获取文件列表及下载

public class FtpHelper { private FtpWebRequest ftpRequest = null; private FtpWebResponse ftpRes...

FtpClient 获取ftp文件列表

FtpClient ftp = (FtpClient) FtpClient.create("mirrors.sohu.com"); ftp.login("Anonymous",...
  • bwlab
  • bwlab
  • 2015年09月10日 22:02
  • 9971
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:FTP服务的LIST指令获取的文件列表信息的解析
举报原因:
原因补充:

(最多只允许输入30个字)