ファイル名からディレクトリ名を取得する


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以降でのみ使用できます。WindowsVistaおよび7は引き続きサポートされているため、PathRemoveFileSpecもサポートされています。
iInspectable 2016

154

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 2016

ディレクトリも扱う場合は、parent_path()from"C:\\folder""C:"。になるという事実に注意してください。
–SemjonMössinger 2016

多くのブーストがstdにアップグレードされるので、これも試してください.... include <filesystem> .... std :: Experimental :: filesystem :: path p( "C:\\ folder \\ foo.txt");
S Meaden 2017年

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
これは、ここでの最良の最小限のソリューションです。
プラズマセル2018年

42

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"

3
.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は標準で移植可能です。
レミ2018年

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
あなたはどの基準について話しているのですか?Boostの多くのものがC ++ std libに追加されたことを知っていますが、ファイルシステムも追加されますか?
McLeary 2013

7
「とにかく次の規格に組み込まれるでしょう」そしてそうではありません
アントンK


6
@AlessandroJacopson Cool、C ++ 17に含まれているようです-en.cppreference.com/w/cpp/filesystem–
Anton K


1

Posixの標準的な方法について誰も言及していないことにとても驚いています

basename / dirnameコンストラクトを使用してください。

manbasename


1
POSIX関数には欠点がないわけではありません。特に、彼らはあなたが(彼らは本当に署名がある意味ですか、渡すことのバッファを修正することができbasname(char * path)ないbasename(const char * path)、と持っているように見えないん実装は、原理的には(それらはスレッドセーフでない可能静的なバッファを使用するために)あなた動的に割り当てられた結果を返すこともできますが、allocそれはC ++では扱いにくいファミリ関数に依存することになります。
dmckee ---元モデレーターの子猫2018

-1

パス名はプラットフォーム固有であるため、標準のC ++はこの点であまり役に立ちません。文字列を手動で解析するか(glowcoderの回答のように)、オペレーティングシステム機能(http://msdn.microsoft.com/en-us/library/aa364232(v=VS.85).aspxなど)を使用するか、おそらく最善のアプローチは、boost :: filesystemのようなサードパーティのファイルシステムライブラリを使用できます。


この規格のC ++ 1zは現在、ブーストファイルシステムライブラリの採用を試みており、プラットフォームの使いやすさの問題ははるかに少なくなっています。少なくとも、MSVCの実験的なヘッダーにはまだ残っています。
kayleeFrye_onDeck 2017

-6

これを使用するだけです:ExtractFilePath(your_path_file_name)


5
これはDelphiの方法であり、C ++の方法ではないと思います。
イアンハンター
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.