Reputation: 21
Assuming I have
String t = "c:/foo/foo1/foo2/foo3/file.txt"
I want to extract "foo3/file.txt"
.
How can I do this (using boost or std)?
Here is what I've been trying to so far:
boost::filesystem::path pathToObject(t);
Using pathToObject.filename()
I can extract the file name of course. And I've played around with t.find_last_of("/")
but I really need like t.find_second_to_last_of("/")
.
Upvotes: 1
Views: 3953
Reputation: 1513
Following method return immediate parent directory.
#include <string>
string getParentDirectory(string& filePath)
{
if (filePath.empty() == false)
{
size_t toPos = filePath.find_last_of('\\') - 1;
if (toPos != string::npos)
{
size_t fromPos = filePath.find_last_of('\\', toPos);
if (fromPos != string::npos)
{
return filePath.substr(fromPos + 1, toPos - fromPos);
}
}
}
return "";
}
int main()
{
string str = "D:\\Devs\\Test\\sprite.png";
string parentDir = getParentDirectory(str);
return 0;
}
It prints the value of parentDir is "Test".
Upvotes: 0
Reputation: 1373
string::find_last_of
has an optional argument which lets you specify how far into the string you are looking.
So you can define
size_t second_to_last = t.find_last_of("/", t.find_last_of("/")-1);
std::string file_with_parent = t.substr(second_to_last+1);
The second argument tells him to only search before the last /
.
WARNING: This might differ from what you want if you have stuff like "C:/bli/bla//blubb.txt"
. In general, paths can be complex and confusing and trying to conquer them with string manipulation will only work for very well-behaved input, which one usually can't assume.
I therefore recommended using a proper tool for this job.* But since the question claimed that find_last_of
wouldn't do the job I felt quite compelled to remind people that the standard facilities are not entirely as impotent as many seem to believe them to be.
*I suspect the boost path lib to be one but I have never worked with it.
Upvotes: 2
Reputation: 1939
It is rather odd to extract a path like that. Maybe you are looking for a relative path? boost filesystem has a tool for that. Be sure to give the documentation a good look over. But to answer your question:
namespace bfs= boost::filesystem;
int main( ) {
bfs::path path( "c:/foo/foo1/foo2/foo3/file.txt" );
bfs::path target( path );
target.remove_filename( );
target= target.filename( ) / path.filename( );
std::cout << target << std::endl;
}
Upvotes: 1
Reputation: 21
Here is the solution I ended up using:
std::string t = pathObject.parent_path().filename().string();
t.append("/");
t.append(pathObject.filename().string());
Using parent_path
gave me just the path. Then I used the filename
to extract just the directory. Then I appended the filename
of the child directory.
Upvotes: 0
Reputation: 2666
I don't have a compiler handy to test it, but based on the example here, this code should basically work or point you in about the right direction. It could probably be simplified a little bit even from what I've written here.
path p1( "c:/foo/foo1/foo2/foo3/file.txt" );
path p2;
for (path::iterator it(p1.end()), int i = 0; it != p1.begin() && i < 2; --it, ++i) {
path temp = p2;
p2 = it;
p2 /= temp;
}
Upvotes: 0