【问题标题】:Need to write at beginning of file with PHP需要用 PHP 在文件开头写
【发布时间】:2010-12-18 03:31:25
【问题描述】:

我正在制作这个程序,并试图找出如何将数据写入文件的开头而不是结尾。 "a"/append 只写到最后,我怎样才能让它写到开头?因为“r+”会这样做,但会覆盖以前的数据。

$datab = fopen('database.txt', "r+");

这是我的整个文件:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <title>Facebook v0.1</title>
        <style type="text/css">
            #bod{
                margin:0 auto;
                width:800px;
                border:solid 2px black;
            }
        </style>
    </head>

    <body>
        <div id="bod">
            <?php
                $fname = $_REQUEST['fname'];
                $lname = $_REQUEST['lname'];
                $comment = $_REQUEST['comment'];
                $datab = $_REQUEST['datab'];
                $gfile = $_REQUEST['gfile'];

                print <<<form
                <table border="2" style="margin:0 auto;">
                    <td>
                        <form method="post"  action="">
                              First Name :
                              <input type ="text"
                                         name="fname"
                                         value="">
                              <br>

                              Last Name :
                                <input type ="text"
                                         name="lname"
                                         value="">
                              <br>

                              Comment :
                              <input type ="text"
                                         name="comment"
                                         value="">
                              <br>
                              <input type ="submit" value="Submit">
                        </form>
                    </td>
                </table>
                form;
                if((!empty($fname)) && (!empty($lname)) && (!empty($comment))){
                    $form = <<<come

                    <table border='2' width='300px' style="margin:0 auto;">
                        <tr>
                            <td>
                                <span style="color:blue; font-weight:bold;">
                                $fname $lname :
                                </span>

                                $comment
                            </td>
                        </tr>
                    </table>
                    come;

                    $datab = fopen('database.txt', "r+");
                    fputs($datab, $form);
                    fclose($datab);

                }else if((empty($fname)) && (empty($lname)) && (empty($comment))){
                    print" please input data";
                } // end table

                $datab = fopen('database.txt', "r");

                while (!feof($datab)){
                    $gfile = fgets($datab);
                    print "$gfile";
                }// end of while
            ?>
        </div>
    </body>
</html>

【问题讨论】:

    标签: php file append


    【解决方案1】:

    又快又脏:

    <?php
    $file_data = "Stuff you want to add\n";
    $file_data .= file_get_contents('database.txt');
    file_put_contents('database.txt', $file_data);
    ?>
    

    【讨论】:

    • 我认为没有更好的方法可以在文件开头插入数据。无论如何,您必须移动文件中当前包含的所有数据。对于较大的文件,您可能需要逐部分读取文件以将其放入内存中。
    • 使用fopen的“c”模式怎么样?这不会写入文件的开头吗?
    • @SSHThis 是的,它确实如此,但它也重写了任何方式:)
    • 使用 FILE_APPEND 避免覆盖
    • 这个文件应该使用多大?那么多个进程同时写入文件的情况呢? fopen() 调用和flock() 调用可以避免这种情况发生吗?
    【解决方案2】:

    如果不想将文件的全部内容加载到变量中,可以使用 PHP 的Streams 功能:

    function prepend($string, $orig_filename) {
      $context = stream_context_create();
      $orig_file = fopen($orig_filename, 'r', 1, $context);
    
      $temp_filename = tempnam(sys_get_temp_dir(), 'php_prepend_');
      file_put_contents($temp_filename, $string);
      file_put_contents($temp_filename, $orig_file, FILE_APPEND);
    
      fclose($orig_file);
      unlink($orig_filename);
      rename($temp_filename, $orig_filename);
    }
    

    它的作用是将要添加的字符串写入临时文件,然后将原始文件的内容写入临时文件的末尾(使用流而不是将整个文件复制到变量中),最后删除原始文件并重命名临时文件以替换它。

    注意:此代码最初基于 Chao Xu 的一篇现已失效的博客文章。此后代码出现分歧,但原帖可以查看in the Wayback Machine

    【讨论】:

    • 谢谢!这很好用,但前提是文件存在(我有一个文件可能丢失的情况。真的很容易解决:if (!file_exsists($filename) [...] )。
    • PHP 有 tempnam() 用于生成唯一文件名。 md5() 与现有文件产生冲突的风险很小。见php.net/manual/en/function.tempnam.php
    • 我使用了这个解决方案,但是将 $tmpname 更改为定义为 $tmpname = tempnam(sys_get_temp_dir(), 'tmp_prepend_'); 这样它使用系统文件夹来存储临时文件,使用标准 php 方法来获取临时名称,使其不太容易被文件系统权限错误。
    • @dubrox VincentNikkelen 谢谢。我已经更新了代码。
    • 如果您对目标文件的权限错误(例如 Apache 无法读取),请尝试在与目标相同的文件夹中创建临时文件,而不是在系统文件夹中。这对我有用。
    【解决方案3】:

    我认为你可以做的是首先读取文件的内容并将其保存在一个临时变量中,现在将新数据插入到文件的开头,然后再附加临时变量的内容。

    $file = file_get_contents($filename); $content = '你的内容' 。 $文件; file_put_contents($content);

    【讨论】:

      【解决方案4】:
      1. w+ 模式而不是a+ 模式打开文件。
      2. 获取要添加的文本长度 ($chunkLength)
      3. 如果需要,将文件光标设置到文件的开头
      4. 从文件中读取$chunkLength字节
      5. 将光标返回到$chunkLength * $i
      6. $prepend
      7. 从第 4 步设置 $prepend 一个值
      8. 执行这些步骤,while EOF

        $handler = fopen('1.txt', 'w+');//1
        rewind($handler);//3
        $prepend = "I would like to add this text to the beginning of this file";
        $chunkLength = strlen($prepend);//2
        $i = 0;
        do{
            $readData = fread($handler, $chunkLength);//4
            fseek($handler, $i * $chunkLength);//5
            fwrite($handler, $prepend);//6
        
            $prepend = $readData;//7
            $i++;
        }while ($readData);//8
        
        fclose($handler);
        

      【讨论】:

      • 在这种情况下 $i * $chunkLength 不是总是 0 吗?
      【解决方案5】:

      您可以使用以下代码在文件的开头和结尾附加文本。

      $myFile = "test.csv";<br>
      $context = stream_context_create();<br>
        $fp = fopen($myFile, 'r', 1, $context);<br>
        $tmpname = md5("kumar");<br>
      
      //this will append text at the beginning of the file<br><br>
        file_put_contents($tmpname, "kumar");<br>
        file_put_contents($tmpname, $fp, FILE_APPEND);<br>
        fclose($fp);<br>
        unlink($myFile);<br>
        rename($tmpname, $myFile);<br><br>
        //this will append text at the end of the file<br>
        file_put_contents($myFile, "ajay", FILE_APPEND);
      

      【讨论】:

        【解决方案6】:

        您可以使用fseek 更改笔记中的指针。

        需要注意的是,如果你使用fwrite,它会删除当前的内容。所以基本上你必须读取整个文件,使用fseek,写入你的新内容,写入文件的旧数据。

        $file_data = file_get_contents('database.txt')
        $fp = fopen('database.txt', 'a');
        fseek($fp,0);
        fwrite($fp, 'new content');
        fwrite($fp, $file_data);
        fclose($fp);
        

        如果你的文件真的很大并且你不想使用太多的内存,你可能想要有两个文件的方法,比如

        $fp_source = fopen('database.txt', 'r');
        $fp_dest = fopen('database_temp.txt', 'w'); // better to generate a real temp filename
        fwrite($fp_dest, 'new content');
        while (!feof($fp_source)) {
            $contents .= fread($fp_source, 8192);
            fwrite($fp_dest, $contents);
        }
        fclose($fp_source);
        fclose($fp_dest);
        unlink('database.txt');
        rename('database_temp.txt','database.txt');
        

        老实说,Ben 的解决方案似乎更直接。

        最后一点:我不知道您在 database.txt 中存储了什么,但使用数据库服务器可能更容易做到这一点。

        【讨论】:

          【解决方案7】:

          一行:

          file_put_contents($file, $data."\r\n".file_get_contents($file));
          

          或者:

          file_put_contents($file, $data."\r\n --- SPLIT --- \r\n".file_get_contents($file));
          

          【讨论】:

            【解决方案8】:

            此代码会记住文件开头的数据,以防止它们被覆盖。接下来它会逐块重写文件中存在的所有数据。

            $data = "new stuff to insert at the beggining of the file";
            $buffer_size = 10000;
            
            $f = fopen("database.txt", "r+");
            $old_data_size = strlen($data);
            $old_data = fread($f, $old_data_size);
            while($old_data_size > 0) {
              fseek($f, SEEK_CUR, -$old_data_size);
              fwrite($f, $data);
              $data = $old_data;
              $old_data = fread($f, $buffer_size);
              $old_data_size = strlen($data);
            }
            fclose($f);
            

            【讨论】:

              【解决方案9】:

              没有办法像您想象的那样写入文件的开头。我猜这是由于操作系统和硬盘驱动器如何查看文件的原因。它有一个固定的开始和扩展的结束。如果你想在中间添加一些东西或开始它需要一些滑动。如果它是一个小文件,只需将其全部读取并进行操作并回写即可。但如果不是,并且如果您总是在开头添加只是反转行顺序,则将结尾视为开始......

              【讨论】:

                【解决方案10】:

                file_get_contents()file_put_contents() 比使用 fopen()fwrite()fclose() 函数使用更多内存:

                $fh = fopen($filename, 'a') or die("can't open file");
                fwrite($fh, $fileNewContent);
                fclose($fh);
                

                【讨论】:

                • 这并没有说明 OP 要求的“前置”功能..
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2014-05-06
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多