파일 이름에서 디렉토리 이름 얻기


85

파일 이름 (C : \ folder \ foo.txt)이 있고 관리되지 않는 C ++에서 폴더 이름 (C : \ folder)을 검색해야합니다. C #에서는 다음과 같이합니다.

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

관리되지 않는 C ++에서 파일 이름에서 경로를 추출하는 데 사용할 수있는 함수가 있습니까?

답변:


20

이를위한 표준 Windows 함수 인 PathRemoveFileSpec이 있습니다. Windows 8 이상 만 지원하는 경우 대신 PathCchRemoveFileSpec 을 사용하는 것이 좋습니다 . 다른 개선 사항 중에서 더 이상 MAX_PATH(260) 문자로 제한되지 않습니다 .


2
이 함수는 이제 더 이상 사용되지 않습니다. Microsoft의 제안은 대신 PathCchRemoveFileSpec 을 사용 하는 것입니다.
기본적으로

1
@Default : PathCchRemoveFileSpec 은 Windows 8부터 만 사용할 수 있습니다. Windows Vista 및 7은 계속 지원되므로 PathRemoveFileSpec 도 지원됩니다 .
IInspectable

153

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()
Peter Cordes

디렉토리를 다룰 수도 있다면 parent_path()from "C:\\folder""C:".
Semjon Mössinger

많은 부스트가 std로 업그레이드되므로 이것을 시도하십시오 .... include <filesystem> .... std :: experimental :: filesystem :: path p ( "C : \\ folder \\ foo.txt");
S Meaden

72

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
이것은 여기서 최고의 최소 솔루션입니다.
plasmacel

39

C ++ 17에는 std::filesystem::path메소드를 사용 하는 클래스가 있습니다 parent_path.

#include <iostream>
#include <filesystem>
namespace fs = std::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"

2
방법도 있습니다 .remove_filename().
Qqwy

1
감사합니다, @Qqwy, 또한 그 방법으로 디렉토리 경로를 사용하여 답변의 접근 방식과 달리 정확하고 예상되는 결과를 얻을 수 있습니다
Herrgott

13

왜 그렇게 복잡해야합니까?

#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
}

10
이것은 휴대용이 아닙니다. Linux의 경로 구분자는 '/'입니다. std :: filesystem :: path는 표준이며 이식 가능합니다.
Rémi

7
 auto p = boost::filesystem::path("test/folder/file.txt");
 std::cout << p.parent_path() << '\n';             // test/folder
 std::cout << p.parent_path().filename() << '\n';  // folder
 std::cout << p.filename() << '\n';                // file.txt

p.parent_path().filename()상위 폴더의 이름을 가져와야 할 수 있습니다 .


5

boost :: filesystem을 사용합니다. 어쨌든 다음 표준에 통합되어 익숙해 질 수 있습니다.


1
어떤 표준에 대해 이야기하고 있습니까? C ++ std lib에 boost의 많은 것들이 추가되었다는 것을 알고 있습니다. 파일 시스템도 추가 될 것입니까?
McLeary 2013-09-05

7
"어쨌든 다음 표준에 통합 될 것입니다"그리고 그것은 아닙니다
Anton K

@AntonK 어쩌면 C ++ 2017?
Alessandro Jacopson

6
@AlessandroJacopson Cool, C ++ 17에 포함 된 것 같습니다 -en.cppreference.com/w/cpp/filesystem
Anton K


1

아무도 Posix에서 표준 방식을 언급하지 않은 것에 놀랐습니다.

basename / dirname구문을 사용하십시오 .

man basename


POSIX 기능에는 단점이 없습니다. 특히 그들은 당신이 전달하는 버퍼를 수정할 수 있으며 (실제로 서명이 basname(char * path)아니라는 것을 의미합니다 basename(const char * path)), 그렇게하지 않는 구현은 스레드를 안전하지 않게 만드는 정적 버퍼를 사용해야하는 것으로 보입니다 (원칙적으로 당신은 동적으로 할당 된 결과를 반환 할 수도 있지만 allocC ++에서는 어색한 패밀리 함수에 의존 하게됩니다.)
dmckee --- 전 중재자 새끼 고양이

-1

표준 C ++는 경로 이름이 플랫폼별로 다르기 때문에 이와 관련하여 많은 작업을 수행하지 않습니다. 수동으로 문자열을 구문 분석하거나 (glowcoder의 답변에서와 같이) 운영 체제 기능 (예 : http://msdn.microsoft.com/en-us/library/aa364232(v=VS.85).aspx )을 사용하거나 가장 좋은 방법은 boost :: filesystem과 같은 타사 파일 시스템 라이브러리를 사용할 수 있다는 것입니다.


표준의 C ++ 1z는 현재 플랫폼 친 화성을 훨씬 덜 문제로 만드는 부스트 파일 시스템 라이브러리를 채택하려고 시도하고 있습니다. 적어도 MSVC의 실험적 헤더에는 여전히 있습니다.
kayleeFrye_onDeck

-6

이것을 사용하십시오 : ExtractFilePath (your_path_file_name)


5
나는 이것이 C ++의 것이 아니라 델파이 방법이라고 생각합니다.
Ian Hunter
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.