从文件路径c ++获取目录
Posted
技术标签:
【中文标题】从文件路径c ++获取目录【英文标题】:get directory from file path c++ 【发布时间】:2011-12-15 10:40:40 【问题描述】:获取文件所在目录的最简单方法是什么?我正在使用它来查找工作目录。
string filename = "C:\MyDirectory\MyFile.bat"
在这个例子中,我应该得到“C:\MyDirectory”。
【问题讨论】:
讨厌:这是一个狭窄的 STL 字符串吗?您应该使用 Unicode 字符串来处理 Windows 上的所有文件。 @Rup:真的吗?查找'/'
和'\'
时,编码是否重要?只要您不将字符串解释为 ASCII/Latin1/任何错误的假设
@sehe 不,当然,如果字符串是 UTF-8,那么您将不会遇到国际化等问题,或者有人向您提供带有日文名称的文件。但只有 UTF-8,当其他一切都使用 UTF-16 时,使用 UTF-8 毫无意义 - 可能包括你首先从哪里获得字符串。
@Rup:所以我们知道你更喜欢 UTF16。供您参考,Windows 将文件名视为 UTF-16 字符的 不透明 数组。另请注意,UTF-16 仍然是一种可变长度的字符编码;它实际上并没有比 UTF-8 买多少。如果您为了实现的简单性而争论 UCS-2(固定长度字符),我会理解的,但话说回来,Windows 还是将其视为 UCS-16
为什么要重新发明***,亲爱的同事们?使用由可能知道自己在做什么的人测试和编写的库。
【参考方案1】:
初始化不正确,需要转义反斜杠:
string filename = "C:\\MyDirectory\\MyFile.bat";
提取目录(如果存在):
string directory;
const size_t last_slash_idx = filename.rfind('\\');
if (std::string::npos != last_slash_idx)
directory = filename.substr(0, last_slash_idx);
【讨论】:
这只是部分的答案,即'在这个例子中,我应该得到......'。要获得正确的解决方案,应使用路径处理库或操作系统调用。 如果文件名(合法地)使用 forward 斜杠则失败。如果文件名是相对的,也无法获取(绝对)目录。还依赖于正确设置编码。当有 Offirmo 的(便携式)Boost 解决方案时,我不会将此标记为“正确”。【参考方案2】:又快又脏:
请注意,您必须还查找/
,因为它在 Windows 上是允许的替代路径分隔符
#include <string>
#include <iostream>
std::string dirnameOf(const std::string& fname)
size_t pos = fname.find_last_of("\\/");
return (std::string::npos == pos)
? ""
: fname.substr(0, pos);
int main(int argc, const char *argv[])
const std::string fname = "C:\\MyDirectory\\MyFile.bat";
std::cout << dirnameOf(fname) << std::endl;
【讨论】:
【参考方案3】:使用Boost.filesystemparent_path() 函数。
例如。参数 c:/foo/bar => c:/foo
更多示例:path decomposition table 和教程here。
【讨论】:
不是每个人都使用 boost。 IIANM,当路径是仅文件名时,这不起作用(即您得到一个空路径)。【参考方案4】:MFC方式;
#include <afx.h>
CString GetContainingFolder(CString &file)
CFileFind fileFind;
fileFind.FindFile(file);
fileFind.FindNextFile();
return fileFind.GetRoot();
或者,甚至更简单
CString path(L"C:\\my\\path\\document.txt");
path.Truncate(path.ReverseFind('\\'));
【讨论】:
第一个例子需要文件存在 没有CString.Truncate方法msdn.microsoft.com/ja-jp/library/ms908314.aspx @OneWorld 这很有趣。不知道我在哪里找到的。CString::Left
怎么样? msdn.microsoft.com/en-us/library/ms928948.aspx
OP 没有询问 MFC,而是专门询问了 c++。
@CraigB MFC 是一个 c++ 库【参考方案5】:
C++17 提供std::filesystem::path。它可能在 C++11 中可用;与 -lstdc++fs 链接。注意该函数不验证路径是否存在;使用 std::filesystem::status 确定文件类型(可能是 filetype::notfound)
【讨论】:
如果一个人使用 c++17 的话,答案很好。据我所知,这就是它最终被采用的地方。【参考方案6】:由于问题很旧,但我想添加一个答案,以便对其他人有所帮助。 在 Visual c++ 中,您也可以使用 CString 或 char 数组
CString filename = _T("C:\\MyDirectory\\MyFile.bat");
PathRemoveFileSpec(filename);
输出:
C:\我的目录
在您的头文件中包含Shlwapi.h
。
MSDN LINK在这里你可以查看示例。
【讨论】:
此代码无法编译。检查 Andrew Kozlov 的答案 很多 c++ 在没有 CString 的系统上。【参考方案7】:您可以使用 stdlib.h 头文件中提供的 _spliltpath 函数。请参考此链接。
http://msdn.microsoft.com/en-us/library/aa273364%28v=VS.60%29.aspx
【讨论】:
鉴于缺少类似 C# 的 dirname 函数,这绝对是最好的方法,因为它不依赖于路径的格式。【参考方案8】:一个非常简单的跨平台解决方案(改编自this example for string::find_last_of
):
std::string GetDirectory (const std::string& path)
size_t found = path.find_last_of("/\\");
return(path.substr(0, found));
这适用于斜杠可以是向后或向前(或混合)的两种情况,因为它只查找字符串 path
中任何一个的最后一次出现。
但是,我个人的偏好是使用 Boost::Filesystem 库来处理这样的操作。一个例子:
std::string GetDirectory (const std::string& path)
boost::filesystem::path p(path);
return(p.parent_path().string());
虽然,如果从字符串中获取目录路径是您需要的唯一功能,那么 Boost 可能有点矫枉过正(特别是因为 Boost::Filesystem 是为数不多的 Boost 库之一,它不是仅头文件)。但是,AFIK、Boost::Filesystem 已被批准包含在 TR2 标准中,但可能要到 C++14 或 C++17 标准(可能是后者,基于this answer)才能完全可用,所以根据您的编译器(以及当您阅读本文时),您甚至可能不再需要单独编译它们,因为它们可能已经包含在您的系统中。例如,Visual Studio 2012 已经可以使用一些 TR2 文件系统组件(根据this post),虽然我还没有尝试过,因为我还在使用 Visual Studio 2010...
【讨论】:
【参考方案9】:从 C++17 开始你可以使用std::filesystem::parent_path:
#include <filesystem>
#include <iostream>
int main()
std::string filename = "C:\\MyDirectory\\MyFile.bat";
std::string directory = std::filesystem::path(filename).parent_path().u8string();
std::cout << directory << std::endl;
【讨论】:
【参考方案10】:这是正确的 winapi 解决方案:
CString csFolder = _T("c:\temp\file.ext");
PathRemoveFileSpec(csFolder.GetBuffer(0));
csFolder.ReleaseBuffer(-1);
【讨论】:
"此函数已弃用。我们建议使用 PathCchRemoveFileSpec 函数代替它。"否则这是正确的答案,所以我+1 OP 没有提到 winapi。【参考方案11】:甲壳虫之道)
#include<tchar.h>
int GetDir(TCHAR *fullPath, TCHAR *dir)
const int buffSize = 1024;
TCHAR buff[buffSize] = 0;
int buffCounter = 0;
int dirSymbolCounter = 0;
for (int i = 0; i < _tcslen(fullPath); i++)
if (fullPath[i] != L'\\')
if (buffCounter < buffSize) buff[buffCounter++] = fullPath[i];
else return -1;
else
for (int i2 = 0; i2 < buffCounter; i2++)
dir[dirSymbolCounter++] = buff[i2];
buff[i2] = 0;
dir[dirSymbolCounter++] = fullPath[i];
buffCounter = 0;
return dirSymbolCounter;
使用:
TCHAR *path = L"C:\\Windows\\System32\\cmd.exe";
TCHAR dir[1024] = 0;
GetDir(path, dir);
wprintf(L"%s\n%s\n", path, dir);
【讨论】:
【参考方案12】:您可以简单地搜索最后一个“\”,然后剪切字符串:
string filePath = "C:\MyDirectory\MyFile.bat"
size_t slash = filePath.find_last_of("\");
string dirPath = (slash != std::string::npos) ? filePath.substr(0, slash) : filePath;
确保在 Linux 中搜索“/”而不是“\”:
size_t slash = filePath.find_last_of("/");
【讨论】:
【参考方案13】:如果你可以访问 Qt,你也可以这样做:
std::string getDirectory(const std::string & file_path)
return QFileInfo(QString(file_path)).absolutePath().toStdString();
【讨论】:
以上是关于从文件路径c ++获取目录的主要内容,如果未能解决你的问题,请参考以下文章