从文件路径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 ++获取目录的主要内容,如果未能解决你的问题,请参考以下文章

如何在iOS Objective c中从没有文件名的目录中获取文件路径

NSFileManager类与文件操作

NSFileManager类与文件操作

NSFileManager类与文件操作

NSFileManager类与文件操作

如何使用 CMD 从文件路径中获取文件夹路径