如何获取当前目录?

103

我想在当前目录(即可执行文件所在的位置)创建一个文件。

我的代码:

LPTSTR NPath = NULL;
DWORD a = GetCurrentDirectory(MAX_PATH,NPath);
HANDLE hNewFile = CreateFile(NPath,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);

我在使用GetCurrentDirectory()时遇到了异常。

为什么会出现异常?


3
#include <unistd.h> char *getcwd(char *buf, size_t size);这段代码是C语言中用于获取当前工作目录的函数。使用该函数需要包含头文件"unistd.h",传入一个指向字符数组的指针buf和数组长度size。函数会将当前工作目录的路径名存储在buf中,并返回该指针。如果执行成功,函数返回值与buf相同;否则,返回NULL。 - Anuswadh
5
请注意:当前目录并不总是exe所在的目录。(例如:c:\users\me> \dir1\dir2\runme.exe,这时你在 c:\users\me 目录下运行位于 \dir1\dir2\ 目录中的exe文件。) - Mercury
3
空指针 - 你会得到一个访问冲突。 - hfrmobile
1
你必须将两个参数都设置为零!!!为了确定所需的缓冲区大小,请将此参数设置为NULL,将nBufferLength参数设置为0。如果nBufferLength> 0且缓冲区指针为NULL-->可能会出现访问冲突。 - hfrmobile
1
由于空指针,可能会发生段错误 - 它没有指向任何内存,因此对其进行解引用可能会导致崩溃(这就是函数内发生的情况)。 - Gregor Hartl Watters
显示剩余4条评论
24个回答

3

您可以通过更简洁的方法从GetModuleFileName()中删除文件名:

TCHAR fullPath[MAX_PATH];
TCHAR driveLetter[3];
TCHAR directory[MAX_PATH];
TCHAR FinalPath[MAX_PATH];
GetModuleFileName(NULL, fullPath, MAX_PATH);
_splitpath(fullPath, driveLetter, directory, NULL, NULL);
sprintf(FinalPath, "%s%s",driveLetter, directory);

希望这有所帮助!

3

GetCurrentDirectory() 获取当前目录,也就是exe文件所在的位置,而这个exe是从哪里调用的。要获取exe文件的位置,可以使用GetModuleFileName(NULL ...)。如果你有exe文件的句柄,或者你可以从GetCommandLine()中推导出来。

正如Butterworth先生指出的那样,你不需要一个句柄。


5
实际上,您不需要一个真正的句柄——一个空句柄可以获得可执行文件名及其路径。 - anon

2
为什么这里没有人考虑使用这个简单的代码?
TCHAR szDir[MAX_PATH] = { 0 };

GetModuleFileName(NULL, szDir, MAX_PATH);
szDir[std::string(szDir).find_last_of("\\/")] = 0;

甚至更简单
TCHAR szDir[MAX_PATH] = { 0 };
TCHAR* szEnd = nullptr;
GetModuleFileName(NULL, szDir, MAX_PATH);
szEnd = _tcsrchr(szDir, '\\');
*szEnd = 0;

1
我在Windows中简单地使用getcwd()方法来实现这个目的,而且效果非常好。代码部分如下所示:
#include <direct.h>

// ...

char cwd[256];
getcwd(cwd, 256);
std::string cwd_str = std::string(cwd);

unistd.h - 没有那个文件或目录 - john k

1

我想,定位当前目录最简单的方法是从命令行参数中切割它。

#include <string>
#include <iostream>

int main(int argc, char* argv[])
{
  std::string cur_dir(argv[0]);
  int pos = cur_dir.find_last_of("/\\");

  std::cout << "path: " << cur_dir.substr(0, pos) << std::endl;
  std::cout << "file: " << cur_dir.substr(pos+1) << std::endl;
  return 0;
}

您可能知道每个程序都会将其可执行文件名作为第一个命令行参数。因此,您可以使用此功能。


非常有用,尤其是对于苹果电脑,不像其他的答案会遇到问题。我也很喜欢您解析字符串以获取目录的方法。感谢您的帮助 - 我投了赞成票。 - msj121
这段代码不会给出当前目录;它将给出可执行文件所在的目录(在某些平台上)。 - Hack5
2
这不会给出当前工作目录。它将提供用于执行二进制文件的路径。如果我执行以下操作:$ ./progargv [0] 将是 "./prog" - Ciro García
这个答案是错误的。当前工作目录与可执行文件所在的目录不同。正如Ciro已经指出的那样。 - Agnel Kurian

0

我的CAE项目中的代码片段,使用Unicode开发环境:

/// @brief Gets current module file path. 
std::string getModuleFilePath() {
    TCHAR buffer[MAX_PATH];
    GetModuleFileName( NULL, buffer, MAX_PATH );
    CT2CA pszPath(buffer);
    std::string path(pszPath);
    std::string::size_type pos = path.find_last_of("\\/");
    return path.substr( 0, pos);
}

只需使用模板CA2CAEXCA2AEX,该模板调用内部API::MultiByteToWideChar::WideCharToMultiByte


0

如果您不想使用std,可以使用以下代码:

char * ExePath() 
{
   static char buffer[MAX_PATH] = { 0 };
   GetModuleFileName( NULL, buffer, MAX_PATH );
   char * LastSlash = strrchr(buffer, '\\');
   if(LastSlash == NULL)
        LastSlash = strrchr(buffer, '/');
    
   buffer[LastSlash-buffer] = 0;
   return buffer;
}

问题是关于获取当前目录,而不是执行路径。 - undefined

0
这取决于你的C++版本,试试这个:
#include <iostream>

#if __cplusplus >= 201703L
// code for C++17 and later
#include <filesystem>
std::string cwd() { return std::filesystem::current_path(); }

#else
// code for earlier versions of c++
#include <unistd.h>
std::string cwd() {
    char buffer[FILENAME_MAX];
    if (getcwd(buffer, FILENAME_MAX) != nullptr) {
        return {buffer};
    }
    return "";
}
#endif


int main() {
    std::cout << cwd();
}


我们还可以从Linux的procfs中获取这个信息,它适用于任何语言。
#include <iostream>
#include <unistd.h>
#include <limits.h>

// ONLY WORKING IN UNIX-LIKE SYSTEMS SUCH AS LINUX
int main() {
    char cwd[PATH_MAX];
    ssize_t size = readlink("/proc/self/cwd", cwd, sizeof(cwd));
    if (size != -1) {
        cwd[size] = '\0'; // Null-terminate the string
        std::cout << "current working directory: " << cwd << std::endl;
    } else {
        std::cerr << "failed to read cwd" << std::endl;
    }

    return 0;
}

问题是在问Windows,不是Linux! - undefined

0
如果您正在使用Poco库,那么这只需要一行代码,我认为它可以在所有平台上运行。
Poco::Path::current()

0

这个文档说...

[out] lpBuffer

指向接收当前目录字符串的缓冲区的指针。 这个以空字符结尾的字符串指定了当前目录的绝对路径。

要确定所需的缓冲区大小,请将此参数设置为NULL,并将nBufferLength参数设置为0。

你正在获取所需的缓冲区大小,而不是路径(NPath为NULL),并且将nBufferLength设置为MAX_PATH

维基百科说...

C++11通过引入一个新的关键字来纠正这个问题,作为一个特殊的空指针常量:nullptr。它是nullptr_t类型,可以隐式转换和比较任何指针类型或指向成员的指针类型。它不能隐式转换或比较整数类型,除了bool。

没有办法区分一个 nullptrNULL(造成访问冲突异常)。

代码应该是这样的:

LPTSTR NewPath;
DWORD a = GetCurrentDirectory(0, NULL);
NewPath = new TCHAR[a];
GetCurrentDirectory(a, NPath);
HANDLE hNewFile = CreateFile(NewPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接