如何验证文件名称在 Windows 中是否有效?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7130885/
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-09-15 17:54:20  来源:igfitidea点击:

How can I validate if a file is name valid in Windows?

cwindowswinapipathfilenames

提问by akmal

Is there a Windows API function that I can pass a string value to that will return a value indicating whether a file name is valid or not?

是否有我可以将字符串值传递给的 Windows API 函数,该函数将返回一个指示文件名是否有效的值?

I need to verify that a file name is valid, and I'm looking for an easy way to do it without re-inventing the wheel. I'm working in straight C, but targeting the Win32 API.

我需要验证文件名是否有效,并且我正在寻找一种无需重新发明轮子的简单方法。我正在直接使用 C 语言,但针对 Win32 API。

If there's no such function built-in, how would I go about writing my own? Is there a general algorithm or pattern that Windows follows for determining file name validity?

如果没有内置这样的函数,我将如何编写自己的函数?Windows 是否有用于确定文件名有效性的通用算法或模式?

采纳答案by Matteo Italia

The problem is not so simple, because it depends from what you consider a "valid file name".

问题并不那么简单,因为它取决于您认为“有效文件名”的内容。

The Windows APIs used with UNC paths will let you happily create a lot of names that are deemed invalid inside normal paths, since with the prefix \\?\you are telling to the Windows APIs to just deliver the path to the filesystem driver, without performing any check; the filesystems themselves often do not really care about what it's used as a file name, once they know that some string is only the file name (i.e. the path/name split has already been done) they generally treat it just as an opaque sequence of characters.

与 UNC 路径一起使用的 Windows API 将让您愉快地创建许多在正常路径中被认为无效的名称,因为使用前缀\\?\告诉 Windows API 只将路径传递到文件系统驱动程序,而不执行任何检查;文件系统本身通常并不真正关心它用作文件名的内容,一旦他们知道某个字符串只是文件名(即路径/名称拆分已经完成),他们通常将其视为一个不透明的序列人物。

On the other hand, if you want to play it safe, you should perform validation according to the rules specified by the MSDN documentyou already linked for Win32 names; I don't think that any file system is allowed to have more stringent rules than these on file naming. On the other hand, violating such requirements, although can be supported by the kernel itself, often give bad headaches to many "normal" applications that expect to deal with "traditional" Win32 paths.

另一方面,如果你想安全一点,你应该根据你已经为 Win32 名称链接的MSDN 文档指定的规则进行验证;我认为任何文件系统都不允许有比文件命名更严格的规则。另一方面,违反这些要求,虽然内核本身可以支持,但通常会给许多希望处理“传统”Win32 路径的“正常”应用程序带来麻烦。

But, in my opinion, if you have to create the file immediately, the best validation you can do is to try to actually create/open the file, letting the OS do such work for you, and be prepared to handle gracefully a failure (GetLastErrorshould return ERROR_BAD_PATHNAME). This will check any other restriction you have on creating such file, e.g. that your application has the appropriate permissions, that the path is not on a readonly medium, ...

但是,在我看来,如果您必须立即创建文件,您可以做的最好的验证是尝试实际创建/打开文件,让操作系统为您完成这些工作,并准备好优雅地处理失败(GetLastError应该返回ERROR_BAD_PATHNAME)。这将检查您对创建此类文件的任何其他限制,例如您的应用程序是否具有适当的权限,该路径不在只读介质上,...

If, for some reason, this is not possible, you may like the shell function PathCleanupSpec: provided the requested file name and the directory in the file system where it has to be created, this function will remove all the invalid characters (I'm not sure about reserved DOS names, they are not listed in its documentation) making the path "probably valid" and notifying you if any modification was made (so you can use it also only for validation).

如果由于某种原因这是不可能的,您可能会喜欢 shell 函数PathCleanupSpec:提供请求的文件名和文件系统中必须在其中创建的目录,此函数将删除所有无效字符(我不是确保保留的 DOS 名称,它们未在其文档中列出)使路径“可能有效”并通知您是否进行了任何修改(因此您也可以仅将其用于验证)。

Notice that this function is marked as "modifiable or removable in any future Windows version", although Microsoft policy is generally that "anything that made it way to a public header will remain public forever".

请注意,此功能被标记为“在任何未来的 Windows 版本中可修改或可移动”,尽管 Microsoft 的政策通常是“任何进入公共标题的内容都将永远保持公开状态”。

回答by penelope

In case you are checking if the file name is valid in the sense "can the file be named like this?" :

如果您正在检查文件名是否在“文件可以这样命名?”的意义上有效吗?:

No, there is no function to directly check that. You will have to write you own function.

不,没有直接检查的功能。您将不得不编写自己的函数。

But, if you know what is a valid file name (the valid file name does now contain any of the following: \ / : * ? " < > |) that shouldn't be such a problem.

但是,如果您知道什么是有效的文件名(有效的文件名现在包含以下任何一项:)\ / : * ? " < > |,那应该不会有这样的问题。

You could perhaps help your self with some of these functions from ctype.h(with them you can check if a specific character belongs to some specific character classes):

您也许可以使用其中的一些功能来帮助您自己ctype.h(使用它们您可以检查特定字符是否属于某些特定字符类):

http://www.cplusplus.com/reference/clibrary/cctype/

http://www.cplusplus.com/reference/clibrary/cctype/

回答by Serge Wautier

This function gives you the list of invalid chars for a filename. Up to you to check that your filename doesn't contain any:

此函数为您提供文件名的无效字符列表。由您来检查您的文件名是否不包含任何内容:

public static char[] Path.GetInvalidFileNameChars()

Docs here.

文档在这里

Note that if you want to validate a directory name, you should use GetInvalidPathChars().

请注意,如果要验证目录名称,则应使用GetInvalidPathChars().

EDIT: Oooops! Sorry, I thought you were on .NET. Using Reflector, here's what this functions boils down to:

编辑:哎呀!抱歉,我以为你在使用 .NET。使用 Reflector,这个函数可以归结为:

'"', '<', '>', '|', 
'##代码##', '\x0001', '\x0002', '\x0003', '\x0004', '\x0005', '\x0006', 
'\a', '\b', '\t', '\n', '\v', '\f', '\r', 
'\x000e', '\x000f', '\x0010', '\x0011', '\x0012', '\x0013', '\x0014', '\x0015', 
'\x0016', '\x0017', '\x0018', '\x0019', '\x001a', '\x001b', '\x001c', '\x001d', 
'\x001e', '\x001f', 
':', '*', '?', '\', '/'

Note that, in addition, there are reserved names such as prn, con, com1, com2,... , lpt1, lpt2,...

注意,除此之外,还有一些保留名称,例如prn, con, com1, com2,... , lpt1, lpt2,...