2010-06-18 6 views
61

У меня есть имя файла (C: \ folder \ foo.txt), и мне нужно получить имя папки (C: \ folder) в неуправляемом C++. В C# я бы сделать что-то вроде этого:Получение имени каталога из имени файла

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

Есть ли функция, которая может быть использована в неуправляемом C++, чтобы извлечь путь из файла?

+1

Вы используете Boost? – AraK

+2

Конечно, тривиально написать такую ​​функцию, но еще лучше использовать функцию стандартной библиотеки языка программирования или API ОС. –

+1

Я не использую boost в этом проекте, извините. –

ответ

18

Существует стандартная функция Windows, для этого, PathRemoveFileSpec. Если вы поддерживаете только Windows 8 и более поздние версии, рекомендуется использовать вместо этого PathCchRemoveFileSpec. Среди других улучшений он больше не ограничен MAX_PATH (260) символами.

+1

Обратите внимание, что эта функция теперь устарела. Предложение от Microsoft заключается в том, чтобы вместо этого использовать [PathCchRemoveFileSpec] (https://msdn.microsoft.com/en-us/library/hh707092%28v=vs.85%29.aspx). – Default

+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

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. –

4

Использование boost :: filesystem. В любом случае, он будет включен в следующий стандарт, чтобы вы могли привыкнуть к нему.

+1

В каком стандарте вы говорите? Я знаю, что в C++ std lib было добавлено много вещей из boost, добавлена ​​файловая система? – McLeary

+6

«В любом случае он будет включен в следующий стандарт» И это не –

+1

@ АнтонK это в tr2 – CoffeeandCode

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/ fileystem/doc/reference.html # path-remove_filename) –

+0

Если вы также можете иметь дело с каталогами, помните о том, что 'parent_path()' из '' C: \\ folder "' приведет к '' C: "' , –

+0

много повышений повышается до std, поэтому также попробуйте это .... включить .... std :: experimental :: filesystem :: path p ("C: \\ folder \\ foo.txt"); –

-3

Просто используйте это: ExtractFilePath (your_path_file_name)

+4

Я считаю, что это метод Delphi, а не что-то в C++. –

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 с классом std::experimental::filesystem::path с использованием метода parent_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 конструкции.

человек basename

Смежные вопросы