我想知道如何检查(在非托管的Visual C ++代码中)字符串是否具有表示文件路径或文件夹路径的有效格式。在这种情况下,物理文件或文件夹路径本身可能存在也可能不存在。在我的情况下,检查正确的字符串格式是主要目标。我需要知道一个字符串是否具有正确的格式作为有效的文件路径或它没有? C#有很多关于它的帖子,但没有一个关于非托管C ++的帖子。如何在Visual C ++中的非托管C ++中完成它?
答案 0 :(得分:6)
唯一100%的确定方法是“试一试”。你可以编写代码来确定简单的情况,但是你总是会遇到需要处理的皱纹,除非你还找出文件所在的驱动器是什么文件系统,因为Windows允许“连接”,这意味着解析整个路径到最后一部分。
这样做要简单得多:
std::ifstream test(proposedName);
if (!test)
{
std::cout << "The file doesn't exist" << std::endl;
}
如果您真的想要花哨,可以查看errno
以确定它是“无效文件名”还是“文件不存在”。但总的来说,尝试再次猜测文件名和路径的有效性毫无意义,因为有太多的规则可能适用于您的特定情况,也可能不适用。
如果你的目录“中途”不存在会变得更加复杂。您只需要解析路径并尝试在路上创建目录[如果整个过程失败则再次删除它]。但是,由于您必须处理非规范路径,因此这更加复杂。 c:\blah\..\.\foo\..\bar\xxx.9\..\..\bleurgh\papa.txt
是有效的文件名吗?要解决这个问题,你必须先将名称规范化。
PathCanonicalize
或者它的朋友会对此有所帮助。但它仍然充满了非常难以解决的令人讨厌的复杂部分。
当然,你可以尝试编写一个正则表达式或其他东西来捕捉简单的案例,但你仍然会得到难以弄清楚的案例。
请注意,在某些情况下,路径可能显示有效,但不是。想象一下,我们有这条道路:c:\directory\foo\bar.txt
。现在,这看起来非常有效,我们可能需要在此内部创建c:\direoctry
和foo
。但是如果c:\directory\foo
是现有文件呢?你会删除文件并在其位置创建一个目录吗?或者你会说它“很好”,然后当你尝试创建目录时失败?我不知道答案,这种复杂性就是为什么我说“唯一可以确保尝试的方法” - 其他一切只是追逐你的尾巴,或接近正确性。
当然,如果我们考虑文件权限,它会变得更加复杂。
[和erenon提出了一个很好的观点 - 即使你现在检查它,在你检查某些内容之间,你实际上开始使用你的路径,你可能已经改变了目录结构,使以前有效的名称无效 - 反之亦然 - 这类问题通常被称为“TOCTOU” - “使用时间检查时间”]
答案 1 :(得分:2)
如果您使用了最新版本的boost,您可以使用为您完成工作的FileSystem并处理所有常见问题(\ vs \\ etc ...)。 它还提供了一些其他功能(文件大小,权限等...)
#include <boost/filesystem.hpp>
string filePath= "C:\Temp\myExample.txt";
if (boost::filesystem::exists(filePath)) // does filePath actually exist?
cout<<"This is a valid file";
else
cout<<"The file does not exist";
这是链接。
http://www.boost.org/doc/libs/1_47_0/libs/filesystem/v3/doc/tutorial.html
它应该在官方C ++中,在这里详细说明。
http://en.cppreference.com/w/cpp/experimental/fs
希望有所帮助,
答案 2 :(得分:1)
我认为Mats Petersson的答案描述了真正的答案。我想指出一个常见的错误。假设以下功能:
bool fileExists(const char* fileName)
{
std::ifstream test(fileName);
return (test) ? true : false;
}
然后以这种方式使用它:
if (fileExists(myFile))
{
// assume myFile is a valid file
// WRONG!
}
这里有一个巨大的竞争条件。检查后但使用前myFile
可能会失效。确保它确实存在的唯一方法是打开它并保持文件句柄。