验证Windows文件名 [英] Validate Windows filename
问题描述
如何确定给定的字符串是否是有效的Windows文件名?我在想一些可以给出一个字符串并返回布尔值的函数.它应该检查是否有不允许的字符(<>:"/\ |?*)和保留字(CON,PRN等).
How do I determine whether a given string is a valid Windows filename? I'm thinking of some function that I can give a string and that returns a boolean. It should check for disallowed characters (<>:"/\|?*) and for reserved words (CON, PRN, et cetera).
isValidWindowsFilename('readme.txt'); // true
isValidWindowsFilename('foo/bar'); // false
isValidWindowsFilename('CON'); // false
I've found a MSDN reference describing exactly what is valid: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
对于Java,我也发现了同样的问题,答案是我需要的,除了它是Java而不是PHP:
I've also found the same question for Java, with an answer that does what I need, except that it's Java and not PHP: Validate a file name on Windows
推荐答案
以下是 Java问题,移植到PHP.
Here's the answer on the Java question, ported to PHP.
/**
* @param string $filename
* @return boolean Whether the string is a valid Windows filename.
*/
function isValidWindowsFilename($filename) {
$regex = <<<'EOREGEX'
~ # start of regular expression
^ # Anchor to start of string.
(?! # Assert filename is not: CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9.
(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])
(\.[^.]*)? # followed by optional extension
$ # and end of string
) # End negative lookahead assertion.
[^<>:"/\\|?*\x00-\x1F]* # Zero or more valid filename chars.
[^<>:"/\\|?*\x00-\x1F\ .] # Last char is not a space or dot.
$ # Anchor to end of string.
#
# tilde = end of regular expression.
# i = pattern modifier PCRE_CASELESS. Make the match case insensitive.
# x = pattern modifier PCRE_EXTENDED. Allows these comments inside the regex.
# D = pattern modifier PCRE_DOLLAR_ENDONLY. A dollar should not match a newline if it is the final character.
~ixD
EOREGEX;
return preg_match($regex, $filename) === 1;
}
请注意,此功能对文件名的长度没有任何限制,但是实际的文件名可能会限制为260或32767个字符,具体取决于平台.
Note that this function does not impose any limit on the length of the filename, but a real filename may be limited to 260 or 32767 chars depending on the platform.
这里有一些测试代码来验证其正确性.
Here's some test code to verify its correctness.
$tests = array(
// Valid filenames
'readme.txt' => true,
'foo.AUX' => true,
'foo.AUX.txt' => true,
'.gitignore' => true, // starting with a period is ok.
// Invalid filenames
'x<y' => false, // less than not allowed.
'x>y' => false, // greater than not allowed.
'q: why not.txt' => false, // colon not allowed.
'He said "hi".doc' => false, // double quote not allowed.
'foo/bar' => false, // Forward slash not allowed.
'foo\\bar' => false, // Backslash not allowed.
'cat readme | backup' => false, // vertical bar (pipe) not allowed.
'ls foo?.rtf' => false, // question mark not allowed
'ls foo*.rtf' => false, // asterisk not allowed
"null\0char" => false, // null character not allowed
'.' => false, // must not end in period
'..' => false, // must not end in period
'period.' => false, // must not end in period
'space ' => false, // must not end with space
// Do not use the following reserved device names for the name of a file:
// CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9.
// Also avoid these names followed immediately by an extension; for example, NUL.txt is not recommended.
'CON' => false,
'prn.txt' => false,
'LPT9.php' => false,
);
// Disallow characters whose integer representations are in the range from 1 through 31
for ($i = 1; $i <= 31; $i++) {
$tests[chr($i)] = false;
}
?>
<style>
.pass {
background-color: #efe;
}
.fail {
background-color: #fee;
}
</style>
<table>
<thead><tr><th>filename</th><th>expected</th><th>actual</th></tr></thead>
<tbody>
<? foreach ($tests as $filename => $expected) {
$actual = isValidWindowsFilename($filename);
?>
<tr><td><?=htmlentities($filename)?></td><td><?= $expected ? 'valid' : 'invalid' ?></td><td class="<?= $expected === $actual ? 'pass' : 'fail' ?>"><?= $actual ? 'valid' : 'invalid' ?></td></tr>
<?
} ?>
</tbody>
</table>
这篇关于验证Windows文件名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!