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(""));