C++中路徑操作
1.獲取當前應用程序所在路徑
1.1 方法:GetModuleFileName
GetModuleFileName聲明:
DWORD WINAPI GetModuleFileName(
_In_opt_ HMODULE hModule,
_Out_ LPTSTR lpFilename,
_In_ DWORD nSize
);
其中:
hModule —— 一個模塊的句柄。可以是一個DLL模塊,或者是一個應用程序的實例句柄。如果該參數為NULL,該函數返回該應用程序全路徑;
lpFilename —— 指定一個字串緩沖區,要在其中容納文件的用NULL字符中止的路徑名;
nSize —— 裝載到緩沖區lpFileName的最大字符數量。經常用_MAX_PATH;
_MAX_PATH是C語言運行時庫中通過#define指令定義的一個宏常量,它定義了編譯器所支持的最長全路徑名的長度。在VC++6.0中,值為260;Windows SDK中也有一個相應的變量MAX_PATH,值也是260。
1.2 獲取全路徑后獲取當前程序的運行目錄(.exe)所在的目錄
TCHAR exeFullPath[MAX_PATH + 1];
GetModuleFileName(NULL, atcExeFullPath, MAX_PATH);
CString path = atcExeFullPath;
path = path.Left(path.ReverseFind('\\'));
2.路徑分解
2.1 方法:_tsplitpath_s
頭文件:stdlib.h
_tsplitpath_s聲明(不同編碼方式下有不同的定義):
errno_t _splitpath_s(
const char * path,
char * drive,
size_t driveNumberOfElements,
char * dir,
size_t dirNumberOfElements,
char * fname,
size_t nameNumberOfElements,
char * ext,
size_t extNumberOfElements
);
errno_t _wsplitpath_s(
const wchar_t * path,
wchar_t * drive,
size_t driveNumberOfElements,
wchar_t *dir,
size_t dirNumberOfElements,
wchar_t * fname,
size_t nameNumberOfElements,
wchar_t * ext,
size_t extNumberOfElements
);
template <size_t drivesize, size_t dirsize, size_t fnamesize, size_t extsize>
errno_t _splitpath_s(
const char *path,
char (&drive)[drivesize],
char (&dir)[dirsize],
char (&fname)[fnamesize],
char (&ext)[extsize]
); // C++ only
template <size_t drivesize, size_t dirsize, size_t fnamesize, size_t extsize>
errno_t _wsplitpath_s(
const wchar_t *path,
wchar_t (&drive)[drivesize],
wchar_t (&dir)[dirsize],
wchar_t (&fname)[fnamesize],
wchar_t (&ext)[extsize]
); // C++ only
各個參數的意義:
[in] path:全路徑
[out] drive:驅動器號,后跟一個冒號(:),如果你不需要驅動器號,可以傳遞NULL
[in] driveNumberOfElements:Drive的緩沖區大小(單字節或寬字節),如果drive為NULL,該參數必須為0
[out] dir:目錄路徑,包括尾部的斜杠,可以使用“\”,“/”或者都使用,如果不需要目錄路徑,可以傳遞NULL
[in] dirNumberOfElements:Dir的緩沖區大小(單字節或者款字節),如果dir為NULL,該參數必須為0
[out] fname:不帶擴展名的文件名,如果不需要文件名,可以傳遞NULL
[in] nameNumberOfElements:Fname的緩沖區大小(單字節或者寬字節),如果fname為NULL,該參數必須為0
[out] ext:文件的擴展名,包括“.”,如果不需要擴展名,可以傳遞NULL
[in] extNumberOfElements:Ext的緩沖區大小(單字節或者寬字節),如果ext為NULL,該參數必須為0
返回值:
成功返回0,失敗返回錯誤代碼 EINVAL
EINVAL情形:
(1) path為NULL;
(2)drive、dir、fname、ext這四個緩沖區指針中存在NULL,但是緩沖區對應的NumberOfElements !=0;
(3)drive、dir、fname、ext這四個緩沖區對應的NumberOfElements =0,但是緩沖區指針不為NULL。
補充:
如果任何一個緩沖區太短而無法包含結果,那么該函數會清空所有緩沖區指向空。設置errno 為ERANGE,並返回ERANGE。
2.2各部分允許最大值
該函數將全路徑分割成四個部分,分別是驅動器,路徑名,文件名(不帶擴展名),擴展名。C語言運行時庫定義的每個部分允許的最大值為分別為_MAX_DRIVE, _MAX_DIR, _MAX_FNAME, _MAX_EXT,而Window SDK中每個部分允許的最大值為分別為_MAX_DRIVE, _MAX_DIR, _MAX_FNAME, _MAX_EXT,這些宏定義在stdlib.h中,如果這四個部分的緩沖區大小超過了定義的允許的最大值,那么會引起 heap corruption.
CRT library與Windows SDK中定義的四個量對應相等,以下是四個宏的定義的最大值:
_MAX_DRIVE 3
_MAX_DIR 256
_MAX_FNAME 256
_Max_EXT 256
3.路徑合成
3.1 方法:_tmakepath_s
頭文件:stdlib.h
_tmakepath_s聲明:
errno_t _makepath_s(
char *path,
size_t sizeInBytes,
const char *drive,
const char *dir,
const char *fname,
const char *ext
);
errno_t _wmakepath_s(
wchar_t *path,
size_t sizeInWords,
const wchar_t *drive,
const wchar_t *dir,
const wchar_t *fname,
const wchar_t *ext
);
template <size_t size>
errno_t _makepath_s(
char (&path)[size],
const char *drive,
const char *dir,
const char *fname,
const char *ext
); // C++ only
template <size_t size>
errno_t _wmakepath_s(
wchar_t (&path)[size],
const wchar_t *drive,
const wchar_t *dir,
const wchar_t *fname,
const wchar_t *ext
); // C++ only
各個參數的意義:
[out] path:完整路徑緩沖區。
[in] sizeInWords:緩沖區大小(以單詞為單位)。
[in] sizeInBytes:緩沖區的大小(以字節為單位)。
[in] drive:包含一個與所需的驅動器對應的字母(A、B 等)和可選的尾隨冒號。 如果缺少冒號,則 _makepath_s 會自動在復合路徑中插入冒號。 如果 drive 為 NULL 或指向空字符串,則在復合 path 字符串中不會顯示驅動器號。
[in] dir:包含目錄路徑,但不包括驅動器指示符或實際文件名。 尾隨斜杠是可選的和正斜杠 (/) 或反斜杠 (\) 或兩者可能使用在單個dir參數。 如果尾部反斜杠 (/ 或\) 指定,則它將自動進行插入。 如果 dir 為 NULL 或指向空字符串,則在復合 path 字符串中不會插入目錄路徑。
[in] fname:包含無任何文件擴展名的基文件名。 如果 fname 為 NULL 或指向空字符串,則在復合 path 字符串中不會插入文件名。
[in] ext:包含實際的文件擴展名(帶有或不帶前導句點 (.))。 如果 _makepath_s 中未顯示句點,則 ext 會自動插入句點。 如果 ext 為 NULL 或指向空字符串,則在復合 path 字符串中不會插入擴展名。
例
// 取得當前應用程序所在路徑,包括程序文件名與后綴名
TCHAR drive[_MAX_DRIVE], dir[MAX_PATH], fname[MAX_PATH], ext[_MAX_EXT];
TCHAR exeFullPath[MAX_PATH];
GetModuleFileName(NULL, exeFullPath, MAX_PATH);
//分解
_tsplitpath_s(exeFullPath, drive, dir, fname, ext);
// 去掉應用程序文件名與后綴名
TCHAR exeFullDir[MAX_PATH];
//合並
_tmakepath_s(exeFullDir, drive, dir, _T(""), _T(""));