2010-06-18 215 views
61

我有一個文件名(C:\ folder \ foo.txt),我需要在非託管C++中檢索文件夾名稱(C:\ folder)。在C#中,我會做這樣的事情:從文件名獲取目錄名稱

string folder = new FileInfo("C:\folder\foo.txt").DirectoryName; 

有沒有可以在非託管C++被用來提取文件名的路徑的功能?

+1

你使用Boost? – AraK 2010-06-18 17:07:55

+2

當然,自己編寫這樣的函數是微不足道的,但使用編程語言的標準庫或OS的API的函數甚至更好。 – 2010-06-18 17:15:49

+1

我沒有在這個項目中使用boost,對不起。 – 2010-06-18 17:40:01

回答

18

有一個標準的Windows功能對於這一點,PathRemoveFileSpec。如果您只支持Windows 8及更高版本,強烈建議使用PathCchRemoveFileSpec代替。除其他改進之外,它不再侷限於MAX_PATH(260)個字符。

+1

請注意,此功能現在已被棄用。微軟的建議是改用[PathCchRemoveFileSpec](https://msdn.microsoft.com/en-us/library/hh707092%28v=vs.85%29.aspx)。 – Default 2016-03-07 17:15:04

+1

@Default:[PathCchRemoveFileSpec](https://msdn.microsoft.com/en-us/library/hh707092.aspx)僅在Windows 8開始可用。由於Windows Vista和7仍受支持,因此[PathRemoveFileSpec] (https://msdn.microsoft.com/en-us/library/bb773748.aspx)。 – IInspectable 2016-07-31 16:51:39

44

來自實例http://www.cplusplus.com/reference/string/string/find_last_of/

// string::find_last_of 
#include <iostream> 
#include <string> 
using namespace std; 

void SplitFilename (const string& str) 
{ 
    size_t found; 
    cout << "Splitting: " << str << endl; 
    found=str.find_last_of("/\\"); 
    cout << " folder: " << str.substr(0,found) << endl; 
    cout << " file: " << str.substr(found+1) << endl; 
} 

int main() 
{ 
    string str1 ("/usr/bin/man"); 
    string str2 ("c:\\windows\\winhelp.exe"); 

    SplitFilename (str1); 
    SplitFilename (str2); 

    return 0; 
} 
1

標準C++不會在這方面爲你做了,因爲路徑名特定於平臺的。您可以手動解析字符串(如glowcoder的答案),使用操作系統工具(例如http://msdn.microsoft.com/en-us/library/aa364232(v=VS.85).aspx),或者可能是最好的方法,您可以使用第三方文件系統庫(如boost :: filesystem)。

+0

該標準的C++ 1z目前正試圖採用boost文件系統庫,目前使平臺友好性更少。至少,它仍然在MSVC的實驗頭文件中。 – 2017-07-08 03:18:12

4

使用boost :: filesystem。無論如何,它將被納入下一個標準,所以你也可以習慣它。

+1

你在說什麼標準?我知道很多來自boost的東西被添加到C++ std lib中,文件系統也會被添加? – McLeary 2013-09-05 12:52:13

+6

「它將被整合到下一個標準中」而且它不是 – 2015-06-22 20:39:09

+1

@AntonK它在tr2 – CoffeeandCode 2015-10-07 09:22:46

121

使用Boost.Filesystem的:

boost::filesystem::path p("C:\\folder\\foo.txt"); 
boost::filesystem::path dir = p.parent_path(); 
+2

p。remove_filename()'將在原地修改'p',[可以比'p = p.parent_path()']更高效地實現(http://www.boost.org/doc/libs/1_60_0/libs/ filesystem/doc/reference.html#path-remove_filename) – 2016-02-09 02:14:30

+0

如果你還可能處理目錄,請注意''C:\\ folder「'中的'parent_path()'將導致'」C:「' 。 – 2016-05-17 12:43:19

+0

很多升壓獲得升級到std所以也試試這個....包括 .... std :: experimental :: filesystem :: path p(「C:\\ folder \\ foo.txt」); – 2017-05-26 15:44:29

-3

只要使用此:ExtractFilePath(your_path_file_name)

+4

我相信這是一個Delphi方法,而不是C++中的東西。 – 2015-11-05 01:29:58

5

爲什麼一定要這麼複雜?

#include <windows.h> 

int main(int argc, char** argv)   // argv[0] = C:\dev\test.exe 
{ 
    char *p = strrchr(argv[0], '\\'); 
    if(p) p[0] = 0; 

    printf(argv[0]);     // argv[0] = C:\dev 
} 
3

根據cppreference.com,實驗頭庫支持C++ 17/1Z存在與使用該方法parent_pathstd::experimental::filesystem::path

#include <iostream> 
#include <experimental/filesystem> 
namespace fs = std::experimental::filesystem; 
int main() 
{ 
    for(fs::path p : {"/var/tmp/example.txt", "/", "/var/tmp/."}) 
     std::cout << "The parent path of " << p 
        << " is " << p.parent_path() << '\n'; 
} 

可能的輸出:

The parent path of "/var/tmp/example.txt" is "/var/tmp" 
The parent path of "/" is "" 
The parent path of "/var/tmp/." is "/var/tmp" 
0

我很驚訝,沒有人提到的Posix

的標準方式請使用basename/dirname結構。

man basename