【问题标题】:How to check if a file has changed?如何检查文件是否已更改?
【发布时间】:2013-02-04 23:43:47
【问题描述】:

我有一个 xml 文件,其中包含应在安装脚本或文件内容更改时加载的数据库信息。我可以在 xml 文件上使用 md5_file() 然后将值存储在数据库中,并在每次运行脚本时将其与文件的哈希值进行比较?它有什么缺点吗?还有其他更快/更简单的方法吗?

【问题讨论】:

  • 是的,您可以使用哈希,或者只是检查文件的修改时间。您可以在搜索引擎中输入您的问题...
  • 我刚刚在搜索引擎中输入了它,结果就到了这里。一个完全合法的问题,这是讨论的最佳场所,imo。

标签: php


【解决方案1】:

这取决于你所说的“改变”是什么意思。如果您需要实际修改内容,那么检查filemtime 是不够的 - 这是一个很棒的第一步,应该先使用,但仅靠它是不够的。

filemtime 与文件内容的哈希(例如md5_file)结合起来,它会有效地工作。

【讨论】:

  • 仅仅使用 md5_file 还不够吗?我只对内容是否不同感兴趣。如果它被相同的内容覆盖或文件名更改并不重要。
  • 嗯,是的。但是,它的成本很高。 filemtime 检查旨在充当更有效的查找。然后,只有修改时间发生了变化,它才会执行昂贵的md5_file 调用。
  • 但文件时间不同但哈希值不同的唯一情况是它被相同的信息覆盖或文件名更改时,对吧?
  • 是的,或者如果在上面调用了touch()函数。
  • 文件不仅仅是字节,当扩展属性发生变化时,md5 对您没有帮助。我希望有一天人们会永远记住这一点,并且有一次实现他们的软件,以便扩展属性变得可用。
【解决方案2】:

最好的办法是存储文件修改时间并将其与您将来检查的文件修改时间进行比较。

if(filemtime('myfile.txt') > $result_set['filemtime']) {
    // file was modified
}

我希望你可以自己做数据库。

【讨论】:

    【解决方案3】:

    也许你可以使用PHP's filemtime() function。简单来说,这个函数获取指定文件的文件修改时间。

    此函数返回一个unix time stamp,因此您需要将上次已知的修改时间保存在某处,以便将其与新值进行比较。

    $modifiedTs = filemtime($filename);
    if ($modifiedTs != $lastModificationTs){
      echo "$filename was modified!";
    }
    

    【讨论】:

    • 你是如何得到 $lastModificationTs 的值的?
    • @cup_of - 这将是您上次调用 filemtime 时的值。当你没有修改时间时,你可以取当前时间戳——然后当你再次调用filemtime并与之前的值进行比较时,它会有所不同,你会知道文件已经改变了。
    【解决方案4】:

    我知道我会回到这里,但这个问题对我有帮助,所以我想分享我用它做了什么,所以虽然这不是问题的答案,但我会将它设为社区 wiki,以便它可以改进(我不是专家)。

    这是一个更大的类的一部分,所以我去掉了其余部分,只提供了适用的代码,并使用一个非常常见的文件将它变成了一个易于理解的示例:

    class ApplicationLogger {
    
        private $logfile, $path;
    
        public function __construct() {
            $this->logfile  = 'error.log';
            $this->path  = '/var/log/apache2/';
        }
    
        public function logState() {
            $files = array(
                'target'  => $this->path . $this->logfile,
                'lastmod' => $this->path . $this->logfile . '_lastmod'
            );
    
            if (file_exists($files['lastmod']) && file_exists($files['target'])) {
                $lfh = fopen($files['lastmod'], 'r');
                while (!feof($lfh)) {
                    $lines[] = fgets($lfh);
                }
                fclose($lfh);
            }
    
            $modified = false;
    
            /**
             * check if we have a matching hash.
             */
            if (isset($lines) && filemtime($files['target']) != $lines[0]) { // mod time mismatch
                if (md5_file($files['target']) != $lines[1]) { // content modified
                    $modified = true;
                }
            }
    
            /**
             * update or create the lastmod file
             */
            if (!file_exists($files['lastmod']) || $modified) {
    
                $current_mod = filemtime($files['target']) . "\n" . md5_file($files['target']);
    
                file_put_contents($files['lastmod'], $current_mod);
                $modified = true;
            }
    
            return $modified;
        }
    }
    

    用法很简单:

    $mod = new ApplicationLogger();
    if ($mod->logState()) {
        // changed do something
    }
    

    根据您的需要调整它,并根据您认为合适的方式进行改进。我希望你能通过编辑这个 CW 来贡献你的改编。

    【讨论】:

      【解决方案5】:

      最简单的方法是比较 file_date - 你可以使用 filemtime 来做这个

      【讨论】:

        猜你喜欢
        • 2018-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-21
        • 2011-04-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多