【问题标题】:Renaming file with PHP用 PHP 重命名文件
【发布时间】:2012-04-20 12:41:40
【问题描述】:

我正在使用我在这里找到的代码,效果很好,但是当我尝试访问子目录中的文件时,它就是不想工作。

它获取一个文件,创建一个要写入的临时文件,然后在文件中查找一些文本并用新文本替换该文本,然后保存更新的文件,然后删除临时文件。

以下工作正常:

        $reading = fopen('links.htm', 'r');
        $writing = fopen('links.tmp', 'w+');

        $replaced = false;

        while (!feof($reading)) {
          $line = fgets($reading);
          if (stristr($line,'::template::')) {
            $line = "replacement line!\n";
            $replaced = true;
          }
          fputs($writing, $line);
        }
        fclose($reading); fclose($writing);
        // might as well not overwrite the file if we didn't replace anything
        if ($replaced) 
        {
          rename('links.tmp', 'links.htm');
        } else {
          unlink('links.tmp');
        }

这不起作用:

        $reading = fopen('path/to/links.htm', 'r');
        $writing = fopen('path/to/links.tmp', 'w+');

        $replaced = false;

        while (!feof($reading)) {
          $line = fgets($reading);
          if (stristr($line,'::template::')) {
            $line = "replacement line!\n";
            $replaced = true;
          }
          fputs($writing, $line);
        }
        fclose($reading); fclose($writing);
        // might as well not overwrite the file if we didn't replace anything
        if ($replaced) 
        {
          rename('path/to/links.tmp', 'path/to/links.htm');
        } else {
          unlink('path/to/links.tmp');
        }

有什么建议吗?

path 是绝对的,我之前在代码中定义了它,并使用它来创建文件和写入文件,但是当我希望上面的代码以同样的方式工作时,它只是不想这样做。

此外,文件夹权限已设置为写入和读取,这也可以正常工作。

在子文件夹中运行代码并且工作正常,但不是从顶级目录。

错误报告已关闭,现在开启:

该进程无法访问该文件,因为它正被另一个进程使用。 (代码:32)

【问题讨论】:

  • 如果您在文件夹“path/to”上尝试 opendir (php.net/manual/en/function.opendir.php) 是否有效?也许您没有所需的访问权限。
  • 是的,它可能只是一个错误的路径问题
  • 它可以很好地读取路径并很好地显示路径中的所有文件。所以那行不通。
  • “不起作用”不是错误消息。发生什么了?你有错误吗?是否启用错误报告?你检查权限了吗?
  • 表示目录已启用写入。并且正在向它写入文件,除了我所说的上面的代码在它必须写入子目录时不起作用。我在它必须写入的目录中对其进行了测试,它也运行良好。

标签: php replace file-handling


【解决方案1】:

因此,经过一周的环顾、测试、破解和重新编码,我找到了一个简单的方法来做到这一点。

由于大部分内容以及 links.htm 文件都是动态创建的,因此很难找到访问文件的位置和时间,因为代码访问了我大约 300 个客户站点并更新了链接文件。

简单修复:

$path = "path/on/server/";

$conn_id = ftp_connect("ftp.testftp.com") or die("Could not connect");
ftp_login($conn_id,"admin","ert456");

$old_file = $path.'links.htm';
$new_file = $path.'_template.htm';
ftp_rename($conn_id, $old_file, $new_file);

$source = fopen($new_file, "w");
$localTarget = "path/to/links.htm";

ftp_fget($conn,$source,$localTarget,FTP_ASCII);

    $reading = fopen('path/to/links.htm', 'r');
    $writing = fopen('path/to/_template.htm', 'w+');

    $replaced = false;

    while (!feof($reading)) {
      $line = fgets($reading);
      if (stristr($line,'::template::')) {
        $line = "replacement line!\n";
        $replaced = true;
      }
      fputs($writing, $line);
    }
    fclose($reading); fclose($writing);
    // might as well not overwrite the file if we didn't replace anything
    if ($replaced) 
    {
      rename('path/to/_template.htm', 'path/to/links.htm');
    } else {
      unlink('path/to/_template.htm');
    }

 $local_file = "path/to/links.htm";

 ftp_put($conn_id, $path, $local_file, FTP_BINARY);

 ftp_close($conn_id);

可能有更简单的方法可以做到这一点,但这对我有用,希望对某人有所帮助。

【讨论】:

    【解决方案2】:

    PHP 需要对该目录具有写入权限才能写入该目录。可能是对当前目录.有写权限,但是对子目录./path/to/没有写权限。

    编辑:如果遇到 PHP 错误,应将其包含在问题中。

    OP 编辑​​后编辑:

    该错误意味着当前打开了links.htm。我看到你在重命名文件之前fclose()ing 文件,所以我猜你可能在其他应用程序(例如浏览器或文本编辑器)中打开了links.htm

    编辑#3:

    如果您没有在另一个应用程序中打开 links.htmlinks.tmp 文件之一,则可能是您使用的是 Windows - 在这种情况下,rename() 调用将在 fclose() 之前执行尽管它在代码中出现在它之后。解决方法是在关闭句柄后添加sleep()调用:

    fclose($reading); fclose($writing);
    sleep(1); // this should allow the handle to be properly closed before the rename() call
    

    【讨论】:

    • 目前已关闭错误报告。通过向其写入文件进行测试,unlink() 在当前目录中工作正常。测试了目录中的代码,效果也很好。
    • @JohanPretorius:我建议你打开这个脚本的错误报告,这样你就可以看到出了什么问题。否则,你很难找到问题所在。
    • @JohanPretorius:如果您没有打开其中一个文件,则可能是时间问题。查看我的编辑。
    • @JohanPretorius:“访问被拒绝”绝对是权限问题。您需要确保 PHP 对这两个目录都有写权限。这意味着您必须为运行 Apache 的用户设置权限,而不是您自己的用户。
    • “可能是您使用的是 Windows - 在这种情况下,rename() 调用将在 fclose() 之前执行,即使它在代码中出现在它之后”@drrcknlsn 源是什么获取此信息?
    猜你喜欢
    • 2014-09-09
    • 2014-01-20
    • 1970-01-01
    • 1970-01-01
    • 2015-01-11
    • 1970-01-01
    • 1970-01-01
    • 2021-10-25
    • 1970-01-01
    相关资源
    最近更新 更多