如何在非托管 C++ 代码中检查字符串是否具有有效的文件路径或目录路径格式?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27587956/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 20:49:10  来源:igfitidea点击:

How to check if a string has a valid file path or directory path format in unmanaged C++ code?

c++filepathstring-formatting

提问by user3769902

I want to know how to check (in unmanaged Visual C++ code) if a string has a valid format to represent file path or folder path. The physical file or folder path itself may or may not exist in this case. To check correct string format is major goal in my case. I need to know if a string has a the right format to be a valid file path or it doesn't have? There are many posts about it for C# but no one for unmanaged C++. How to do it in unmanaged C++ in Visual C++?

我想知道如何检查(在非托管 Visual C++ 代码中)字符串是否具有表示文件路径或文件夹路径的有效格式。在这种情况下,物理文件或文件夹路径本身可能存在也可能不存在。就我而言,检查正确的字符串格式是主要目标。我需要知道一个字符串是否具有作为有效文件路径的正确格式,或者它没有?有很多关于 C# 的文章,但没有一篇关于非托管 C++ 的文章。如何在 Visual C++ 中的非托管 C++ 中做到这一点?

回答by Mats Petersson

The ONLY 100% certain way is to "try it". You can write code to determine simple cases, but there are will always be wrinkles that you need to deal with, unless you ALSO find out what filesystem the drive is that the file lives on, which, since Windows allows "junctions", means parsing the entire path down to the final part.

唯一 100% 确定的方法是“尝试”。您可以编写代码来确定简单的情况,但总会有一些问题需要处理,除非您还找出文件所在的驱动器所在的文件系统,因为 Windows 允许“连接”,这意味着解析整个路径直到最后一部分。

It is much simpler to do :

这样做要简单得多:

  std::ifstream test(proposedName); 
  if (!test)
  {
      std::cout << "The file doesn't exist" << std::endl;
  }

If you really want to be fancy, you could take a look at errnoto figure out if it was "invalid filename" or "file doesn't exist". But in general, it's pointless to try to second guess the validity of a filename and path, since there are WAY too many rules that may or may not apply to YOUR particular case.

如果你真的想花哨,你可以看看errno它是“无效文件名”还是“文件不存在”。但总的来说,尝试再次猜测文件名和路径的有效性是没有意义的,因为有太多规则可能适用于您的特定情况,也可能不适用。

It gets more complicated if you have directories "halfway" that doesn't exist. You'd simply have to parse the path and try creating the directory on the way [and deleting it again if the whole process fails]. However, this is further complicated by the fact that you have to deal with non-canonical paths. Is c:\blah\..\.\foo\..\bar\xxx.9\..\..\bleurgh\papa.txta valid filename? To solve this you'd have to FIRST canonicalize the name.

如果您有不存在的“中途”目录,情况会变得更加复杂。您只需解析路径并尝试在途中创建目录[如果整个过程失败,则再次删除它]。但是,由于您必须处理非规范路径,这一点变得更加复杂。是c:\blah\..\.\foo\..\bar\xxx.9\..\..\bleurgh\papa.txt有效的文件名吗?要解决这个问题,您必须首先规范化名称。

PathCanonicalizeor it's friends would help with this. But it's still full of nasty complicated bits that are VERY hard to solve.

PathCanonicalize或者它的朋友会帮助解决这个问题。但它仍然充满了很难解决的令人讨厌的复杂位。

Sure, you can try writing a regex or something to catch the simple cases, but you will still end up with cases which are hard to figure out.

当然,你可以尝试编写一个正则表达式或其他东西来捕捉简单的情况,但你仍然会遇到难以弄清楚的情况。

Note that there are situations when a path may appear valid, but isn't. Imagine that we have this path: c:\directory\foo\bar.txt. Now, that looks perfectly valid, we may have to create c:\direoctryand fooinside this. But what if c:\directory\foois an already existing file? Would you remove the file and create a directory in its place? Or would you say it's "fine" and then fail when you try to create the directory? I don't know the answer, and this sort of complication is why I say "the only way to make sure is to try it" - everything else is just chasing your tail, or approximating the correctness.

请注意,在某些情况下,路径可能看起来有效,但实际上并非如此。试想一下,我们有这样的路径:c:\directory\foo\bar.txt。现在,这看起来完全有效,我们可能必须在其中创建c:\direoctryfoo。但是如果c:\directory\foo是一个已经存在的文件呢?您会删除该文件并在其位置创建一个目录吗?或者您会说它“很好”然后在您尝试创建目录时失败?我不知道答案,这种复杂性就是为什么我说“唯一确保尝试的方法” - 其他一切都只是追赶你的尾巴,或者接近正确性。

And of course, it gets even more complicated if we take file permissions into account.

当然,如果我们将文件权限考虑在内,它会变得更加复杂。

[And erenon makes a good point - even if you check it now, between the point you check something, and you actually start using your path, you may well have had changes to the directory structure making a previously valid name invalid - or vice versa - this sort of problem is often called "TOCTOU" - "Time of Check to Time of Use"]

[而且erenon 提出了一个很好的观点——即使你现在检查它,在你检查某些东西和你实际开始使用你的路径之间,你很可能已经对目录结构进行了更改,使以前的有效名称无效——反之亦然- 这种问题通常被称为“TOCTOU”——“检查时间到使用时间”]

回答by Gabriel

If you incorporate a recent version of boost you can use FileSystem that does the job for you and takes care of all the usual problems (\ vs \\ etc...). It also provides some other facilities (filesize, permissions etc...)

如果您合并了最新版本的 boost,您可以使用 FileSystem 为您完成工作并处理所有常见问题(\ vs \\ 等...)。它还提供了一些其他功能(文件大小、权限等...)

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

Here is the link.

链接在这里。

http://www.boost.org/doc/libs/1_47_0/libs/filesystem/v3/doc/tutorial.html

http://www.boost.org/doc/libs/1_47_0/libs/filesystem/v3/doc/tutorial.html

It should be in the official C++ at some point, full details here.

它应该在某个时候在官方 C++ 中,完整的细节在这里。

http://en.cppreference.com/w/cpp/experimental/fs

http://en.cppreference.com/w/cpp/experimental/fs

Hope that helps,

希望有所帮助,

回答by erenon

I think the answer of Mats Petersson describes the true answer. I'd like to point out a common error. Assume the following function:

我认为 Mats Petersson 的回答描述了真实的答案。我想指出一个常见的错误。假设有以下函数:

bool fileExists(const char* fileName)
{
  std::ifstream test(fileName); 
  return (test) ? true : false;
}

Then using it this way:

然后以这种方式使用它:

if (fileExists(myFile))
{
  // assume myFile is a valid file
  // WRONG!
}

There is a huge race condition here. myFilemight become invalid after checking but before using it. The only way to make sure it does exist is to open it and keep the file handle around.

这里有一个巨大的竞争条件。myFile检查后但在使用之前可能会失效。确保它确实存在的唯一方法是打开它并保留文件句柄。