移动文件指针向上一行(PHP)?

时间:2009-08-23 11:08:06

标签: php file-io

我正在尝试自动化网站上的sitemap.xml文件,因为内容不断变化。我当前打开文件以追加:fopen($file_name, 'a');,以便我可以添加新的标记集。但是,我只是注意到整个站点地图文件必须以标签结束,这意味着每次打开文件时,我都需要将文本追加到文件的末尾,而不是从末尾追加到1行。 / p>

基本上,在打开文件后如何移动文件指针以便我可以实现这个目的?感谢。

更新:以下是网站地图的样子:

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.google.com/schemas/sitemap/0.84">
    <url>
        <loc>...</loc>
        <lastmod>2009-08-23</lastmod>
        <changefreq>weekly</changefreq>
        <priority>0.8</priority>
    </url>
    </urlset>

所以每当我追加时,我都需要添加必须在结束<url>..</url>标记之前的</urlset>部分。我已经有了可以将xml附加到文件末尾的代码。我只需要弄清楚如何在结束标记之前附加新部分

5 个答案:

答案 0 :(得分:7)

使用php fseek()寻找文件的末尾(使用filesize()查找),然后向后迭代一行。读取最后一行并暂时存储它。用您要插入的内容覆盖最后一行,然后附加先前存储的临时行。

要向后迭代一行,请使用fseek与fgetc()

结合使用
$offset = filesize($fhandle) - 1;
fseek($fhandle, $offset--); //seek to the end of the line
while(fgetc($fhandle) != '\n') {
   fseek($fhandle, $offset--);
}

现在你的内部文件指针应该指向最后一行之前的一行。当然,当你的文件只有一行时,你将不得不处理极端情况,但我会让你弄清楚细节;)

现在将最后一行存储在tmp变量

$lastline = fgets($fhandle);
fseek($fhandle, $offset); //go back to where the last line began

插入您的行,并在文件末尾附加最后一行

fwrite($fhandle, $myLine);
fwrite($fhandle, $lastline);

答案 1 :(得分:3)

如果没有看到你正在谈论的XML,并且不知道你想要添加什么(请提供这些以获得完整的编码答案),我可以建议这种方法...

  1. 使用PHP XML解析器(http://uk3.php.net/manual/en/ref.xml.php
  2. 加载整个文件
  3. 将新元素添加到XML
  4. 使用fopen()和fwrite()函数保存(我猜你还是这样做)
  5. 正如我所说,如果没有看到XML或更多代码,很难提供和回答

答案 2 :(得分:1)

加入Charles Ma的答案。您可以将其保存在名为sitemapper.php的文件中,并使用GET查询调用此文件,但我建议您添加更多安全性,如果您可能有并发写入,则建议使用flock()。

使用它的另一个原因是如果您使用的是没有SimpleXMLParser的PHP4。

<?php
/*--------------------------------------------------------
==================
sitemapper.php 1.0
==================
Pass me a path to a page, and I will add it to your XML sitemap.

Paths are passed from root, as 
www.example.com/sitemapper.php?path=/test/index.html
for a page at http://www.example.com/test/index.html

This script is faster than parsing XML, for large sitemaps.
--------------------------------------------------------*/

if (isset($_GET[path])) {

    // Get the path to the new page to add to our sitemap.
    $fname = urldecode($_GET[path]);

    // Real path to files is different on some hosts.
    $current_path = realpath(dirname(__FILE__));

    if (!is_file("./sitemap.xml")){

        $xml = '';
        $xml =  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"."\n";
        $xml .= "<urlset xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd\" xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">"."\n";
        $xml .= "</urlset>"."\n";

        $sitemap = fopen("./sitemap.xml", "x");             
        fwrite($sitemap, $xml); 
        fclose($sitemap);
    }

    // Write sitemap.xml entry for current file
    // This is a very old-school 'C' style of doing it.
    // The modern way would be to open the file in an XML parser, 
    // add the elements you want, serialise it to a new file 
    // and swap them over (so that nothing reads the XML in 
    // the middle of you writing it)
    //
    // However I expect this XML file to become *huge* shortly
    // So I am avoiding use of the PHP XML Parser.

    $date = date('Y-m-dTH:i:sP', time()); //Date in w3c format for XML sitemaps

    $xml = '';
    $xml .= "<url>"."\n";
    $xml .= "   <loc>http://". $_SERVER["HTTP_HOST"] . $fname . "</loc>"."\n";
    $xml .= "   <lastmod>" . $date . "</lastmod>"."\n";
    $xml .= "   <priority>0.50</priority>"."\n";
    $xml .= "   <changefreq>never</changefreq>"."\n";
    $xml .= "</url>"."\n";            

    if ($sitemap = @fopen("./sitemap.xml", "r+")) 
    {

        // seek to the end of the file, then iterate backwards one line. 
        // read the last line and store it temporarily. overwrite the 
        // last line with what you want to insert, then append the 
        // temporary line you stored previously.

        $offset = filesize("./sitemap.xml") - 1;

        fseek($sitemap, ($offset - 1)); //seek to before the last character in the file
        while( (($char = fgetc($sitemap)) !== "\n") && ($offset > -2000) && ($offset < 2000)) {
            // Go backwards, trying to find a line-break.
            // The offset range is just a sanity check if something goes wrong.
            $offset = $offset - 1;
            fseek($sitemap, $offset);
        }  

        $offset = $offset + 1; // Come to the beginning of the next line
        fseek($sitemap, $offset);
        $lastline = fgets($sitemap); // Copy the next line into a variable
        fseek($sitemap, $offset); //go back to where the last line began

        fwrite($sitemap, $xml); // add the current entry
        fwrite($sitemap, $lastline); // add the </urlset> line back.

        fclose($sitemap);
    }
}
?>

答案 3 :(得分:0)

保留文件的两个版本:站点地图和没有结束标记的tmp。 当你想扩展时,首先扩展tmp一个;然后将其复制到sitemap,并在那里添加结束标记。

答案 4 :(得分:0)

fseek($ fp,-n,SEEK_END);,但您必须将文件打开为“r +”而不是“a”。

像这样处理XML通常不是一个好主意;依赖于精确的字节位置是非常脆弱的。更好的方法是在XML解析器中打开文件,添加所需的元素,将其序列化为新文件并将其交换(以便在编写它时不会读取XML)。

在数据库支持的站点上,您还可以考虑使用PHP本身动态生成站点地图XML。