फ़ाइल नाम से निर्देशिका नाम प्राप्त करना


85

मेरा एक फ़ाइल नाम है (C: \ folder \ foo.txt) और मुझे अप्रबंधित C ++ में फ़ोल्डर का नाम (C: \ folder) पुनः प्राप्त करना होगा। C # में मैं ऐसा कुछ करूंगा:

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

क्या कोई फ़ंक्शन है जो फ़ाइल नाम से पथ निकालने के लिए अप्रबंधित C ++ में उपयोग किया जा सकता है?

जवाबों:


20

इसके लिए एक मानक विंडोज फ़ंक्शन है, PathRemoveFileSpec । यदि आप केवल विंडोज 8 और बाद में समर्थन करते हैं, तो इसके बजाय PathCchRemoveFileSpec का उपयोग करने की अत्यधिक अनुशंसा की जाती है । अन्य सुधारों के बीच, यह अब MAX_PATH(260) वर्णों तक सीमित नहीं है ।


2
ध्यान दें कि यह फ़ंक्शन अब पदावनत हो गया है। Microsoft का सुझाव इसके बजाय PathCchRemoveFileSpec का उपयोग करना है।
डिफ़ॉल्ट

1
@Default: PathCchRemoveFileSpec केवल विंडोज 8 के साथ ही उपलब्ध है। चूंकि Windows Vista और 7 अभी भी समर्थित हैं, इसलिए PathRemoveFileSpec है
IInspectable

153

Boost.Filesystem का उपयोग करना:

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


यदि आप निर्देशिकाओं से निपट सकते हैं तो इस तथ्य parent_path()से अवगत रहें कि "C:\\folder"इससे परिणाम क्या होगा "C:"
सेमजोन मोसेिंगर

बहुत से स्टैड में अपग्रेड हो जाता है इसलिए इसे भी आज़माएं .... इसमें शामिल हैं <filesystem> .... std :: प्रयोगात्मक :: filesystem :: path p ("C: \\ folder \\ foo.txt");
एस मेडन

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
धन्यवाद, @Qwwy, यह उत्तर से दृष्टिकोण के विपरीत सही और अपेक्षित परिणाम प्राप्त करने के लिए उस पद्धति के साथ निर्देशिका पथ का उपयोग करने की अनुमति देता है
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
यह पोर्टेबल नहीं है। लिनक्स में पथ विभाजक '/' है। std :: filesystem :: पथ मानक और पोर्टेबल है।
रेमी

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

बूस्ट का उपयोग करें :: फाइलसिस्टम। इसे वैसे भी अगले मानक में शामिल किया जाएगा ताकि आपको इसकी आदत हो जाए।


1
आप किस मानक की बात कर रहे हैं? मुझे पता है कि C ++ std lib में बूस्ट से बहुत सारी चीजें जोड़ी गई थीं, फाइलसिस्टम भी जोड़ा जाएगा?
मैक्लेरी

7
"इसे वैसे भी अगले मानक में शामिल किया जाएगा" और यह नहीं है
एंटोन के

@AntonK शायद C ++ 2017?
एलेसांद्रो जैकपसन

6
@AlessandroJacopson कूल, ऐसा लगता है कि C ++ 17 में शामिल है - en.cppreference.com/w/cpp/filesystem
एंटोन के


1

मुझे बहुत आश्चर्य हुआ कि किसी ने भी पॉज़िक्स में मानक तरीके का उल्लेख नहीं किया है

इस्तेमाल करें basename / dirname निर्माण का ।

आदमी का नाम


POSIX फ़ंक्शन उनकी कमियों के बिना नहीं हैं। विशेष रूप से वे उस बफर को संशोधित कर सकते हैं जिसे आप पास करते हैं (वे वास्तव में मतलब है कि हस्ताक्षर है basname(char * path)और नहीं basename(const char * path)), और कार्यान्वयन जो ऐसा नहीं करते हैं जो एक स्थिर बफर का उपयोग करते हैं जो उन्हें थ्रेड-असुरक्षित बनाता है (सिद्धांत रूप में आप गतिशील रूप से आवंटित परिणाम भी लौटा सकता है, लेकिन यह आपको allocपारिवारिक कार्यों पर निर्भर करता है जो C ++ में अजीब है)।
dmckee --- पूर्व-मध्यस्थ बिल्ली का बच्चा

-1

मानक सी ++ इस संबंध में आपके लिए बहुत कुछ नहीं करेगा, क्योंकि पथ के नाम प्लेटफ़ॉर्म-विशिष्ट हैं। आप मैन्युअल रूप से स्ट्रिंग को पार्स कर सकते हैं (जैसा कि ग्लोकोडर के उत्तर में है), ऑपरेटिंग सिस्टम सुविधाओं का उपयोग करें (जैसे http://msdn.microsoft.com/en-us/library/aa364232(v=VS.85).aspx ), या शायद सबसे अच्छा तरीका है, आप एक तृतीय-पक्ष फाइल सिस्टम लाइब्रेरी का उपयोग कर सकते हैं जैसे बढ़ावा :: फाइल सिस्टम।


मानक का C ++ 1z वर्तमान में बूस्ट फाइलसिस्टम लाइब्रेरी को अपनाने का प्रयास कर रहा है क्योंकि अब प्लेटफॉर्म-मित्रता को एक मुद्दे के रूप में कम किया जा रहा है। यह MSVC के प्रायोगिक शीर्षलेखों में अभी भी है, कम से कम।
kayleeFrye_onDeck

-6

बस इसका उपयोग करें: ExtractFilePath (your_path_file_name)


5
मेरा मानना ​​है कि यह एक डेल्फी पद्धति है, न कि C ++ में कुछ।
इयान हंटर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.