1. 程式人生 > >FTP伺服器LIST指令獲取的檔案列表資訊解析(UNIX格式)

FTP伺服器LIST指令獲取的檔案列表資訊解析(UNIX格式)

最近在寫FTP客戶端的程式,但是在傳送LIST指令之後,不知如何解析伺服器發回的列表資訊,上網一查,略坑,居然都是同一篇文章,居然還都是原創,而且對於UNIX格式下的檔案列表資訊並沒有解析完成,因為沒有判斷出檔案的年份,附帶的程式也不完善。

經過幾翻查詢資料,終於知道了正確的解析方法,與各位同道一起分享,請各位指正。

FTP伺服器執行的系統一般分為windows和UNIX作業系統,系統不一樣,FTP伺服器返回的資訊也不一樣,有兩種格式,如下:

1、MS-DOS檔案列表格式解析:

這種格式的講解就略過了,百度很容易就找到了。

2、現在看UNIX檔案列表格式的解析:

UNIX檔案列表格式解析:

drwx----- 1 user group            0   Sep 20 18:50 360Rec

-rwx------ 1 user group           24 Jun 11 2009 autoexec.bat

drwx----- 1 user group            0  Jul 14 2009 Documents and Settings

drwx----- 1 user group            0 Feb 08 2013 User

drwx----- 1 user group            0 Jun 28 22:16 Users

以上是我在程式設計時伺服器返回的部分檔案列表資訊。

UNIX檔案列表每一個檔案資訊分為9個部分,現在說每個部分代表的意義:

第一部分drwx-----,共9個字元,第一個字元d表示該檔案是目錄,-表示是檔案,之後的r表示可讀,w表示可寫,x表示可執行

第二部分,第二部分,第三部分,對我來說意義不大,略過不提

第五部分:如果是目錄,則為0(<DIR>),如果是檔案,則為檔案大小

第六部分:檔案的月份

第七部分:檔案的月份的某一天

第八部分:或者為小時分鐘,或者為年份

第九部分:檔名

資訊提取方式,以提取第一部分資訊為例:

CString msg = "drwx----- 1 user group            0   Sep 20 18:50 360Rec",str;
	msg.TrimLeft();//去掉左側的空格,製表符,回車
	int n = msg.Find(" ");//查詢第一個空格,返回空格的位置,或者-1
	str = msg.Left(n);//將msg中第n個位置左側的字元賦值給str,提取了第一部分資訊
	msg = msg.Mid(n+1);//將msg中第n個位置之後的所以字元賦值給msg

迴圈解析……,即可得到所有部分的資訊。

現在說檔案時間資訊的處理:

我想大家應該在糾結第八部分如何處理,如何得到具體的年份,如果第八部分為年份,自然萬事大吉,如果不是年份,我們怎麼得到年份呢?其實檔案列表資訊是有具體規定的。我們再處理時間時,必須與當前的時間進行比較,這裡的當前時間是指:程式的執行的具體時間。

如果第八部分為HH:MM(H:小時,M:分鐘)格式,獲取當前時間的年year、月month和日day(2014年3月3日),比較檔案列表中的月份和當前月份,比如第一個檔案列表資訊中的月份是Sep,9月大於當前月份3月,那麼該檔案的年份就是當前年份-1,即是2013年;如果小於當前月份,那麼該檔案的年份就是當前年份。

這樣就算第八部分是HH:MM,我們也能得到檔案的年份了。

以下是我的解析函式:

while(1)//處理整個檔案列表資訊
{//整個檔案列表資訊中,每個檔案資訊是以"\r\n"來隔開的
	n = st.Find("\r\n");//查詢st中第一個"\r\n"的位置
	if(n == -1)//若不存在,則結束迴圈
		break;
	filelist = st.Left(n);//將st中從0開始到第一個"\r\n"的字串賦值給filelist,即第一個檔案資訊
	st = st.Mid(n+2);//將st從第一個"\r\n"的位置開始,到結束的字元賦值給st,即保留剩餘檔案資訊
	if(filelist[0] == 'd')
	{
		//若為目錄,相應處理程式
	}
	else
	{
		//若為檔案,相應處理程式
	}
}
CString GetSegmentInfo(CString sFileInfo,int nSegment)//分割檔案資訊,第一個形參是某個檔案的資訊,第二個形參是提取的第幾部分,從0開始,到8結束
{
	int nIdx = -1;
	int nSeg = 0;
	CString sInfo = "";
	sFileInfo.TrimLeft();//消除前導的空格,製表符,換行符
	while(nSeg < nSegment+1)//逐段切隔
	{
		nIdx = sFileInfo.Find(" ");//以空格為切隔
		sInfo = sFileInfo.Left(nIdx);
		if(nSeg < nSegment)//檔名有空格時也可以分割出來
			sFileInfo = sFileInfo.Mid(nIdx+1);//如果提取的是檔名,最後一次Mid不能執行,否則當檔名中有空格時,得到的檔名不對
		sFileInfo.TrimLeft();//過濾左側的空格符
		nSeg++;
	}
	if(nSegment == 8)
		sInfo = sFileInfo;
	return sInfo;
}

CString GetTime(CString month,CString day,CString tt)//解析檔案的年月日
{
	CString mon[12] ={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"},filetime;
	CTime _time=time(NULL);
	int mm = 0,year,dd = atoi(day);
	for(int i = 0;i < 12; i++)
	{
		if(month == mon[i])
		{
			mm = i+1;//取得檔案資訊中的月份
			break;
		}
	}
	if(tt.Find(':') == -1)//如果第八部分中沒有字元':',則第八部分是年份
		year = atoi(tt);
	else//如果不是年份
	{
		if(mm > _time.GetMonth())//若大於當前月份,則年份為當前年份-1
			year = _time.GetYear()-1;
		else//否則為當前年份-1
			year = _time.GetYear();
	}
	filetime.Format("%d/%d/%d",year,mm,dd);
	return filetime;
}