不区分大小写的文件_存在大型文件列表

问题描述 投票:0回答:2

我有一个包含大量文件的服务器文件夹,使用 guid 值随机命名(示例文件:

c3c1a48e-a798-41bd-bd70-66ffdc619963.jpg
)。

我需要对该文件夹进行不区分大小写的搜索,因为可能存在同一文件名的大写(或混合大小写)版本。 (我无法将现有文件转换为全部小写文件名。)

这个问题的答案 file_exists() 的 PHP 不区分大小写版本 提供了一个函数(如下所示),它将整个文件夹“通配”到一个数组中,然后对数组中的每个项目进行 foreach 搜索。

这似乎有点慢/效率低下,尤其是在搜索包含许多(数千个)文件的文件夹时。

是否有更有效的方法来进行不区分大小写的文件名搜索?或者使用 foreach 循环 - 如下面的代码所示 - “足够高效”?

(这是上面问题推荐的代码)

function fileExists($fileName, $caseSensitive = true) {

    if(file_exists($fileName)) {
        return $fileName;
    }
    if($caseSensitive) return false;

    // Handle case insensitive requests            
    $directoryName = dirname($fileName);
    $fileArray = glob($directoryName . '/*', GLOB_NOSORT);
    $fileNameLowerCase = strtolower($fileName);
    foreach($fileArray as $file) {
        if(strtolower($file) == $fileNameLowerCase) {
            return $file;
        }
    }
    return false;

}

php file search
2个回答
0
投票

我无法发表评论,尽管这可以回答你的问题:不。就你目前的状态而言,看起来你必须使用这种逻辑。 -但是- 您可以创建逻辑来获取那些具有大写字母的文件,并在文件夹中使用

copy($filename,strtolower($filename))
将它们变为小写,然后删除具有大写字母的旧文件名。 。然后,在将来添加更多文件时,
strtolower($new_file_name)
,然后再将文件添加到系统中。我同意你的观点,但这种逻辑确实看起来很慢,尤其是对于数千个文件。

这与您所说的无法重命名/转换文件名相矛盾,尽管一旦您这样做,这将是您唯一一次必须重命名它们。


0
投票

有时我想创建一个不区分大小写的自动加载器,所以我在这里使用了示例: https://www.php-fig.org/psr/psr-4/examples/ ...并对其进行了一些修改。

我添加了一个为

glob()
创建图案的方法。它创建一个模式,其中每个字符都以大写和小写形式存在,只要它在相同的情况下有所不同,那么就不需要额外的模式,因此点和斜线没有大写或小写版本。 path/file.php 看起来像 [pP][aA][tT][hH]/[fF][iI][lL][eE].[pP][hH][pP].

它并不完美,因为在某些情况下,utf8 中不止一个替代字符,因此,如果小写和大写与给定的字符不同,它还会将其添加到可能的字符的模式中,但只是这个而不是所有替代方案。

/**
 * Convert path and filename to a case insensitive pattern for glob().
 *  
 * @param string $path
 * @return string
 */
private function createCaseInsensitivePattern(string $path) {
    
    $chars = mb_str_split($path);
    $pattern = '';
    foreach ($chars as $char) {
        $lower = mb_strtolower($char);
        $upper = mb_strtoupper($char);
        if ($char == $lower && $char == $upper) {
            $pattern .= $char;
        } else {
            $pattern .= '['.$lower.$upper.($char != $lower && $char != $upper?$char:'').']';
        }
        $pattern .= $char == '/' || $char == '\\' ? $char:('');
    }
    return $pattern;
}

然后我用 else 情况扩展了

requireFile()
方法。 因此,如果未在正确的情况下找到文件,则它只需调用
createCaseInsensitivePattern()
方法并对结果执行
glob()
操作。如果没有任何东西适合,那么它只是返回 false。

/**
 * If a file exists, require it from the file system.
 *
 * @param string $file The file to require.
 * @return bool True if the file exists, false if not.
 */
protected function requireFile(string $file)
{
    
    if (file_exists($file)) {
        require $file;
        return true;
    } else {
        $filePattern = $this->createCaseInsensitivePattern($file);
        $possibleFiles = glob($filePattern);
        foreach ($possibleFiles as $currentFile) {
            if (file_exists($currentFile)) {
                require $currentFile;
                return true;
            }
        }
    }
    return false;
}

如果您只想执行 file_exists,只需删除以

require
开头的两行。

© www.soinside.com 2019 - 2024. All rights reserved.