1. 程式人生 > >利用C++獲取某一資料夾下的所有檔名,並獲取不帶字尾的檔名字

利用C++獲取某一資料夾下的所有檔名,並獲取不帶字尾的檔名字

來源:https://www.cnblogs.com/fnlingnzb-learner/p/6424563.html

那麼到底如何查詢檔案呢?我們需要一個結構體和幾個大家可能不太熟悉的函式。這些函式和結構體在<io.h>的標頭檔案中,
結構體為struct _finddata_t ,函式為_findfirst、_findnext和_fineclose

_finddata_t 結構體:儲存檔案各種資訊

unsigned atrrib:檔案屬性的儲存位置。它儲存一個unsigned單元,用於表示檔案的屬性。檔案屬性是用表示的,主要有以下一些用無符號整數(2的幾次冪)定義的巨集
_A_ARCH(存檔)、_A_HIDDEN(隱藏)、_A_NORMAL(正常)、_A_RDONLY(只讀)、_A_SUBDIR(資料夾)

、_A_SYSTEM(系統)。
這些都是在<io.h>中定義的巨集,可以直接使用,而本身的意義其實是一個無符號整型(只不過這個整型應該是2的幾次冪,從而保證只有一位為1,而其他位為0)。既然是位表示,那麼當一個檔案有多個屬性時,它往往是通過位或的方式,來得到幾個屬性的綜合。例如只讀+隱藏+系統屬性,應該為:_A_HIDDEN | _A_RDONLY | _A_SYSTEM 。
time_t time_create:這裡的time_t是一個變數型別(長整型?相當於long int?),用來儲存時間的,我們暫時不用理它,只要知道,這個time_create變數是用來儲存檔案建立時間的就可以了

time_t time_access:檔案最後一次被訪問的時間。
time_t time_write:檔案最後一次被修改的時間。
_fsize_t size:檔案的大小。這裡的_fsize_t應該可以相當於unsigned整型,表示檔案的位元組數。
char name[_MAX_FNAME]:檔案的檔名。這裡的_MAX_FNAME是一個常量巨集,它在<stdlib.h>標頭檔案中被定義,表示的是檔名的最大長度。
以此,我們可以推測出,struct _finddata_t ,大概的定義如下:

struct _finddata_t
{
             unsigned attrib;
             time_t time_create; // -1 for FAT file systems
             time_t time_access;
             time_t time_write;
             _fsize_t size;
             char name[_MAX_FNAME];
};

函式:

  1. long _findfirst( char *filespec, struct _finddata_t *fileinfo ); 
    返回值:如果查詢成功的話,將返回一個long型的唯一的查詢用的控制代碼(就是一個唯一編號)。這個控制代碼將在_findnext函式中被使用。若失敗,則返回-1。
    filespec:標明檔案的字串,可支援萬用字元。比如:*.c,則表示當前資料夾下的所有後綴為C的檔案。
    fileinfo :這裡就是用來存放檔案資訊的結構體的指標。這個結構體必須在呼叫此函式前宣告,不過不用初始化,只要分配了記憶體空間就可以了。函式成功後,函式會把找到的檔案的資訊放入這個結構體中。
  2. int _findnext( long handle, struct _finddata_t *fileinfo );
    返回值:若成功返回0,否則返回-1。
     handle:即由_findfirst函式返回回來的控制代碼。
    fileinfo:檔案資訊結構體的指標。找到檔案後,函式將該檔案資訊放入此結構體中。
  3. int _findclose( long handle );
    返回值:成功返回0,失敗返回-1。
    handle :_findfirst函式返回回來的控制代碼。

函式實現:

獲取某一資料夾下的所有檔名

void getFiles(string path, vector<string>& files)
{
	//檔案控制代碼:檔案的唯一標識
	//long hFile = 0;//32位能跑動
	intptr_t hFile = 0;//因為_findfirst和_findnext返回intptr_t而非long型
	//定義儲存檔案資訊的結構體
	struct _finddata_t fileinfo;
	string p;
	if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1)//string轉化為c_str即C型別的字串
	{
		do
		{
			//如果是目錄,迭代之  
			//如果不是,加入列表  
			if ((fileinfo.attrib &  _A_SUBDIR))//&:attrib和_A_SUBDIR做一次與運算,返回1則為_A_SUBDIR(資料夾)
			{
				if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
					getFiles(p.assign(path).append("\\").append(fileinfo.name), files);//遞迴
			}
			else
			{
				files.push_back(p.assign(path).append("\\").append(fileinfo.name));
			}
		} 
		while (_findnext(hFile, &fileinfo) == 0);
		_findclose(hFile);
	}
}

只取檔名,去除字尾(應用於利用數字命名並需要對齊排序的檔案)

string removeSuffix(string fileName)
{
	const char* full_name = fileName.c_str();
	const char*  mn_first = full_name;
	int tmp = strlen(full_name);//長度不包含'/0'
	const char*  mn_last = full_name /*+ strlen(full_name)*/;
	if (strrchr(full_name, '\\') != NULL)//去除路徑,只留檔名
		mn_first = strrchr(full_name, '\\') + 1;
	else if (strrchr(full_name, '/') != NULL)//去除linux下的檔案路徑
		mn_first = strrchr(full_name, '/') + 1;
	if (strrchr(full_name, '.') != NULL)
		mn_last = strrchr(full_name, '.');//獲取.*字尾
	if (mn_last < mn_first)//地址比較
		mn_last = full_name + strlen(full_name);
	fileName.assign(mn_first, mn_last);//引數10001.jpg和.jpg
	return fileName;
}

註釋:
函式名稱: strrchr 
函式原型:char *strrchr(const char *str, char c); 
所屬庫: string.h 
函式功能:查詢一個字元c在另一個字串str中末次出現的位置(也就是從str的右側開始查詢字元c首次出現的位置),並返回這個位置的地址。如果未能找到指定字元,那麼函式將返回NULL。使用這個地址返回從最後一個字元c到str末尾的字串。 
對應於C++的find_last_of函式,不同點,返回位置索引。