【问题标题】:Extracting the immediate parent directory from a file path using boost使用 boost 从文件路径中提取直接父目录
【发布时间】:2016-12-31 20:28:11
【问题描述】:

假设我有

String t = "c:/foo/foo1/foo2/foo3/file.txt"

我要提取"foo3/file.txt"

我该怎么做(使用 boost 或 std)?

到目前为止,这是我一直在尝试的:

boost::filesystem::path pathToObject(t);

使用pathToObject.filename()我当然可以提取文件名。我玩过t.find_last_of("/"),但我真的需要t.find_second_to_last_of("/")

【问题讨论】:

  • 你试过什么?你为什么不上Tour
  • 感谢您的回答和我的@joshj777。这是我最终使用的解决方案: std::string t = pathObject.parent_path().filename().string(); t.append("/"); t.append(pathObject.filename().string());
  • 您应该接受以下答案之一。 (它可以是你自己的,但不是必须的。)
  • 谢谢!赫尔曼!长期潜伏者和用户。期待更多参与。
  • 一个没有接受答案的已解决问题会触发我的not-an-actual-OCD。那么,你能帮我解决这个问题吗?

标签: c++ boost std boost-filesystem


【解决方案1】:

string::find_last_of 有一个 optional argument,它可以让您指定要查看的字符串的深度。

所以你可以定义

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);

第二个参数告诉他只搜索之前最后一个/

警告:如果您有 "C:/bli/bla//blubb.txt" 之类的内容,这可能与您想要的有所不同。一般来说,路径可能很复杂且令人困惑,尝试通过字符串操作来征服它们只会适用于行为良好的输入,而这通常是无法假设的。

因此,我建议使用适当的工具来完成这项工作。* 但由于问题声称 find_last_of 不会完成这项工作,我觉得非常有必要提醒人们标准设施并不像许多人认为的那样完全无能为力相信他们。

*我怀疑 boost path lib 是一个,但我从未使用过它。

【讨论】:

  • 我喜欢简洁。人们往往会忘记标准库实用程序。但是,如果我想要路径操作,我不会亲自去这里,因为路径在现实生活中并不是那么可预测的。仍然 +1
  • @sehe Whelp,因为关于这个不能可靠工作的注释显然没有出现,我将它扩展为一个大胆的警告。现在开心? (=
  • 哦。我以前很开心。我也没有看到很多反对票,所以你不必太担心。
  • 安全总比抱歉好。如果有人因为某个白痴盲目地复制我的代码而死亡,我希望能够说“但我警告他们”。这几乎与一开始就没有人死亡一样好!
  • 另外,我不明白你所说的“[not] many downvotes”。
【解决方案2】:

提取这样的路径是相当奇怪的。也许您正在寻找相对路径? boost 文件系统有一个工具。一定要好好看看documentation。但要回答你的问题:

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

【讨论】:

  • 是的,我实际上是在寻找文件的父目录。
  • 然后删除filename,剩下的filename就是你的父目录。那是在我发布的代码中。
【解决方案3】:

我没有方便的编译器来测试它,但根据此处的示例,这段代码应该基本上可以工作或为您指明正确的方向。即使从我在这里写的内容来看,它也可能会简化一点。

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

【讨论】:

  • 这太复杂了。绝对是不好的建议,但它确实有一种奇怪的美感。 (=
  • “奇异之美”是因为它比大多数其他解决方案可能要通用得多。这个解决方案可以抽象为 n 级路径,而不是只需要多几行代码的 2 级。
  • 我的也可以。只需循环到n,始终记住最后一个斜线ith 的位置。对我来说,美妙之处在于使用 两个 迭代器,我认为不应该使用单个迭代器。
【解决方案4】:

这是我最终使用的解决方案:

std::string t = pathObject.parent_path().filename().string();
t.append("/");
t.append(pathObject.filename().string());

使用parent_path 给了我路径。然后我使用filename 仅提取目录。然后我附加了子目录的filename

【讨论】:

  • 如果是我。我会将路径对象保留为增强路径。无需从字符串到路径再到字符串。我在答案中添加了重要的一行。
【解决方案5】:

以下方法返回直接父目录。

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

它打印出parentDir的值为“Test”。

【讨论】:

    猜你喜欢
    • 2011-02-14
    • 2011-09-01
    • 2015-11-08
    • 2015-04-26
    • 1970-01-01
    • 2012-10-04
    • 1970-01-01
    • 2015-05-21
    相关资源
    最近更新 更多