1. 程式人生 > >c++ 得到指定目錄下指定檔名 windows vs2010

c++ 得到指定目錄下指定檔名 windows vs2010

c++ 得到指定目錄下指定檔名方法頗多,網上尋找總結有:

1. 主要思路是使用第三方庫 dirent.h 檔案來完成

資料結構:

struct dirent
{
    long d_ino;                 /* inode number 索引節點號 */
    off_t d_off;                /* offset to this dirent 在目錄檔案中的偏移 */
    unsigned short d_reclen;    /* length of this d_name 檔名長 */
    unsigned char d_type;        /* the type of d_name 檔案型別 */    
    char d_name [NAME_MAX+1];   /* file name (null-terminated) 檔名,最長255字元 */
}
 
struct __dirstream
  {
    void *__fd;                        /* `struct hurd_fd' pointer for descriptor.  */
    char *__data;                /* Directory block.  */
    int __entry_data;                /* Entry number `__data' corresponds to.  */
    char *__ptr;                /* Current pointer into the block.  */
    int __entry_ptr;                /* Entry number `__ptr' corresponds to.  */
    size_t __allocation;        /* Space allocated for the block.  */
    size_t __size;                /* Total valid data in the block.  */
    __libc_lock_define (, __lock) /* Mutex lock for this structure.  */
  };

typedef struct __dirstream DIR;

stackoverflow示例
DIR *dir;
struct dirent *ent;
if ((dir = opendir ("c:\\src\\")) != NULL)
{
/* print all the files and directories within directory */
    while ((ent = readdir (dir)) != NULL)
    {
        printf ("%s\n", ent->d_name);
    }
    closedir (dir);
}
else
{
    /* could not open directory */
    perror ("");
    return EXIT_FAILURE;
}

部落格示例

#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <stdio.h>

int main(){
    DIR    *dir;
    struct    dirent    *ptr;
    dir = opendir("."); ///open the dir

    while((ptr = readdir(dir)) != NULL) ///read the list of this dir
    {
        #ifdef _WIN32
            printf("d_name: %s\n", ptr->d_name);
        #endif
        #ifdef __linux
            printf("d_type:%d d_name: %s\n", ptr->d_type,ptr->d_name);
        #endif
    }
    closedir(dir);
    return 0;
}


2. 主要思路是利用 boot filesystem module 來完成。如果是交叉平臺上,最好的方法是使用庫來完成。

給定一個路徑和檔名,以下函式迭代地在該目錄和該目錄下的子目錄中搜索該檔案,返回一個布林值,和如果成功找到的檔案的路徑。

bool find_file( const path & dir_path,         // in this directory,
                const std::string & file_name, // search for this name,
                path & path_found )            // placing path here if found
{
  if ( !exists( dir_path ) ) return false;
  directory_iterator end_itr; // default construction yields past-the-end
  for ( directory_iterator itr( dir_path );
        itr != end_itr;
        ++itr )
  {
    if ( is_directory(itr->status()) )
    {
      if ( find_file( itr->path(), file_name, path_found ) ) return true;
    }
    else if ( itr->leaf() == file_name ) // see below
    {
      path_found = itr->path();
      return true;
    }
  }
  return false;
}

3. 主要思路是使用io.h提供的 handle_File =_findfirst( filespec, &fileinfo) 與 _findnext( handle_File, &fileinfo) 函式完成。

其中 handle_File 是檔案控制代碼

filespec 是指定檔案特性

fileinfo 是裝有檔案資訊的結構體

函式名稱:_findfirst
函式功能:搜尋與指定的檔名稱匹配的第一個例項,若成功則返回第一個例項的控制代碼,否則返回-1L
函式原型:long _findfirst( char *filespec, struct _finddata_t *fileinfo );
標頭檔案:io.h

函式名稱:_findnext

函式功能:搜尋與_findfirst函式提供的檔名稱匹配的下一個例項,若成功則返回0,否則返回-1

函式原型:int _findnext( intptr_t handle, struct _finddata_t *fileinfo);

標頭檔案:io.h

程式舉例(http://baike.baidu.com/view/1186290.htm)

#include<io.h>
#include<stdio.h>
int main()
{
    long Handle;
    struct _finddata_t FileInfo;
    if((Handle=_findfirst("D:\\*.txt",&FileInfo))==-1L)
        printf("沒有找到匹配的專案\n");
    else
    {
        printf("%s\n",FileInfo.name);
        while(_findnext(Handle,&FileInfo)==0)
            printf("%s\n",FileInfo.name);
        _findclose(Handle);
    }
    return 0;
}

相關部落格有:

4. 一個函式就夠,不需要三方庫

函式如下:

#include <Windows.h>

vector<string> get_all_files_names_within_folder(string folder)
{
    vector<string> names;
    char search_path[200];
    sprintf(search_path, "%s*.*", folder.c_str());
    WIN32_FIND_DATA fd; 
    HANDLE hFind = ::FindFirstFile(search_path, &fd); 
    if(hFind != INVALID_HANDLE_VALUE) 
    { 
        do 
        { 
            // read all (real) files in current folder
            // , delete '!' read other 2 default folder . and ..
            if(! (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) 
            {
                names.push_back(fd.cFileName);
            }
        }while(::FindNextFile(hFind, &fd)); 
        ::FindClose(hFind); 
    } 
    return names;
}

以上不少方法參見此貼

實踐過方法3,並簡化為只訪問指定目錄下指定檔案(不訪問字目錄):

#ifndef GETDIRECTORY_REDUCED_H
#define GETDIRECTORY_REDUCED_H

#include <stdlib.h>
#include <direct.h>
#include <string>
#include <io.h>

class CBrowseDir
{
private:
	char m_szDir[_MAX_PATH];
	int m_nFileCount;   //儲存檔案個數
	long int handle_File;

public:
	CBrowseDir();

	//設定初始目錄為dir,指定檔案filespec,如果返回false,表示目錄不可用
	bool SetDir(const char *dir, const char *filespec);

	//遍歷目錄dir下由filespec指定的檔案,不訪問子目錄,如果返回false,表示中止遍歷檔案
	bool BrowseDir(const char *filespec);

	//每次呼叫給出該目錄下的下一個指定檔案的路徑,成功返回true
	bool CBrowseDir::NextFile(std::string &);

	//返回檔案個數
	int GetFileCount();
};

#endif

#include <stdlib.h>
#include <direct.h>
#include <string>
#include <io.h>
#include <stdio.h>
#include <iostream>
#include "GetDirectory_Reduced.h"

using namespace std;

CBrowseDir::CBrowseDir()
{
	//用當前目錄初始化m_szDir
	_getcwd(m_szDir,_MAX_PATH);

	//如果目錄的最後一個字母不是'\',則在最後加上一個'\'
	int len=strlen(m_szDir);
	if (m_szDir[len-1] != '\\')
	{
		m_szDir[len]='\\';
		m_szDir[len+1]='\0';
	}//strcat(m_szDir,"\\");

	m_nFileCount=0;
}

bool CBrowseDir::SetDir(const char *dir, const char *filespec)
{
	//先把dir轉換為絕對路徑
	if (_fullpath(m_szDir,dir,_MAX_PATH) == NULL)
		return false;

	//判斷目錄是否存在,並轉到指定目錄m_szDir下
	if (_chdir(m_szDir) != 0)
		return false;

	//如果目錄的最後一個字母不是'\',則在最後加上一個'\'
	int len=strlen(m_szDir);
	if (m_szDir[len-1] != '\\')
	{
		m_szDir[len]='\\';
		m_szDir[len+1]='\0';
	}//strcat(m_szDir,"\\");

	_chdir(m_szDir);//轉換到指定目錄下
	_finddata_t fileinfo;
	handle_File=_findfirst(filespec,&fileinfo);//首先查詢dir中符合要求的檔案
	if(handle_File==-1)
		return false;

	return true;
}

bool CBrowseDir::BrowseDir(const char *filespec)
{
	_chdir(m_szDir);

	//首先查詢dir中符合要求的檔案
	long hFile;
	_finddata_t fileinfo;
	if ((hFile=_findfirst(filespec,&fileinfo)) != -1)
	{
		do
		{
			//檢查如果不是子資料夾,則進行處理
			if (!(fileinfo.attrib & _A_SUBDIR))
			{
				string filename(m_szDir);//用string來處理,避免strcpy、strcat帶來的warning
				filename+=fileinfo.name;
				cout << filename << endl;
				m_nFileCount++;//檔案數加1
			}
		} while (_findnext(hFile,&fileinfo) == 0);
		_findclose(hFile);
	}
	return true;
}

bool CBrowseDir::NextFile(string &nextfilename)
{
	_finddata_t fileinfo;
	while(_findnext(handle_File,&fileinfo) == 0)
	{
		//檢查如果不是子資料夾,則進行處理
		if((fileinfo.attrib & _A_SUBDIR))
			continue;
		string filename(m_szDir);//用string來處理,避免strcpy、strcat帶來的warning
		filename+=fileinfo.name;
		cout << filename << endl;
		nextfilename=filename;
		m_nFileCount++;//檔案數加1
		return true;
	}
	_findclose(handle_File);
	return false;
}

//返回檔案個數
int CBrowseDir::GetFileCount()
{
	return m_nFileCount;
}