使用PHP替换大文件中的字符

时间:2022-10-17 11:34:29

I tried to replace single quotes in a large XML file(110MB) with this code but an error occured. I need a code that can handle atleast 3GB XML file.

我尝试使用此代码替换大型XML文件(110MB)中的单引号但发生错误。我需要一个可以处理至少3GB XML文件的代码。

Error Message:

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 20449728 bytes) in C:\xampp\htdocs\replace.php on line 10

致命错误:第10行的C:\ xampp \ htdocs \ replace.php中允许的内存大小为134217728个字节(试图分配20449728个字节)

<?php
    replace_file('electronics.xml', "'", "&#39;");

    function replace_file($path, $string, $replace)
    {
        $file = fopen($path, 'a+');
        while (feof($file) === false)
        {
            $str=file_get_contents($path);
            $str=str_replace($string, $replace, fgets($file));
        }
        fclose($file);
}
echo "replace done";
?>

3 个解决方案

#1


Reading a large file into php is not recommended. Call a command line that is appropriate, like sed

不建议将大文件读入php。调用适当的命令行,如sed

Reference: http://www.grymoire.com/Unix/Sed.html

#2


Simplify:

$str = str_replace( "'","&#39;",file_get_contents('electronics.xml'));

This is just very wrong:

这是非常错误的:

Opening XML

    $file = fopen($path, 'a+');

While Loop for no reason, fgets reads to end of file, so loop completes on first iteration.

虽然Loop无缘无故,fgets读取到文件末尾,因此循环在第一次迭代时完成。

    while (feof($file) === false)  
    {

reading in entire contents of same file file again, for no purpose

再次读取同一文件的全部内容,没有任何意义

        $str=file_get_contents($path);  

Reading in entire file, no length specified, so reading to EOF

读取整个文件,没有指定长度,因此读取到EOF

        $str=str_replace($string, $replace, fgets($file));  
    }
    fclose($file); 

Nothing accomplished.

#3


    ////
 //PHP 5.3 + Class find and replace string in files
 //
 //by Bruce Afruz 
 //
 //2013
 //
 //example usage for single file:
 //
 //$new = new fileReplacement('./');
 //$new->setExt("check.php");
 //$new->changeContents("hello", "goodbye");
 //
 //example usage for multiple files:
 //
 //$new = new fileReplacement('./test');
 //$new->setExt("*.html");
 //$new->changeContents("hello", "goodbye");
 //
 //to change directory:
 //
 //$new = new fileReplacement('./test');
 //$new->setDir("./test2");
 //$new->setExt("*.html");
 //$new->changeContents("hello", "goodbye");
 ////


 class fileReplacement 
 {
  private $ext , $dir ;
  public function getDir() {
   return $this->dir;
  }
  public function setDir($dir) {
   $this->dir = $dir;
  }
   public function getExt() {
   return $this->ext;
  }
  public function setExt($ext) {
   $this->ext = $ext;
  }
 function __construct($dir) {
   $this->dir = $dir;
  }

  public function rglob($pattern = '*', $flags = 0, $path = '') {

  chdir($this->getDir());
  $paths = glob($path . '*', GLOB_MARK | GLOB_ONLYDIR | GLOB_NOSORT);
  $files = glob($path . $pattern, $flags);
  foreach ($paths as $path) {
  $files = array_merge($files, $this->rglob($pattern, $flags, $path));
  }
  return $files;
 }

 public function changeContents($replace , $sentence , $flags = 0, $path = '') {
 $all = $this->rglob($this->getExt() , $flags, $path);
 foreach ($all as $file) {

  $filename = $file;
  $handle = fopen($filename, "r");
  $contents = fread($handle, filesize($filename));
  fclose($handle);
  $contents = str_replace($replace , $sentence, $contents);

  if (is_writable($filename)) {
   if (!$handle = fopen($filename, 'w+')) {
    echo "Cannot open file ($filename)
";
    exit;
   }

   // Write $contents to our opened file.
   if (fwrite($handle, $contents) === FALSE) {
    echo "Cannot write to file ($filename)
";
    exit;
   }

   echo "Success, wrote content to file ($filename)
";

   fclose($handle);
  } else {
   echo "The file $filename is not writable
";
  }
 }
 }}

#1


Reading a large file into php is not recommended. Call a command line that is appropriate, like sed

不建议将大文件读入php。调用适当的命令行,如sed

Reference: http://www.grymoire.com/Unix/Sed.html

#2


Simplify:

$str = str_replace( "'","&#39;",file_get_contents('electronics.xml'));

This is just very wrong:

这是非常错误的:

Opening XML

    $file = fopen($path, 'a+');

While Loop for no reason, fgets reads to end of file, so loop completes on first iteration.

虽然Loop无缘无故,fgets读取到文件末尾,因此循环在第一次迭代时完成。

    while (feof($file) === false)  
    {

reading in entire contents of same file file again, for no purpose

再次读取同一文件的全部内容,没有任何意义

        $str=file_get_contents($path);  

Reading in entire file, no length specified, so reading to EOF

读取整个文件,没有指定长度,因此读取到EOF

        $str=str_replace($string, $replace, fgets($file));  
    }
    fclose($file); 

Nothing accomplished.

#3


    ////
 //PHP 5.3 + Class find and replace string in files
 //
 //by Bruce Afruz 
 //
 //2013
 //
 //example usage for single file:
 //
 //$new = new fileReplacement('./');
 //$new->setExt("check.php");
 //$new->changeContents("hello", "goodbye");
 //
 //example usage for multiple files:
 //
 //$new = new fileReplacement('./test');
 //$new->setExt("*.html");
 //$new->changeContents("hello", "goodbye");
 //
 //to change directory:
 //
 //$new = new fileReplacement('./test');
 //$new->setDir("./test2");
 //$new->setExt("*.html");
 //$new->changeContents("hello", "goodbye");
 ////


 class fileReplacement 
 {
  private $ext , $dir ;
  public function getDir() {
   return $this->dir;
  }
  public function setDir($dir) {
   $this->dir = $dir;
  }
   public function getExt() {
   return $this->ext;
  }
  public function setExt($ext) {
   $this->ext = $ext;
  }
 function __construct($dir) {
   $this->dir = $dir;
  }

  public function rglob($pattern = '*', $flags = 0, $path = '') {

  chdir($this->getDir());
  $paths = glob($path . '*', GLOB_MARK | GLOB_ONLYDIR | GLOB_NOSORT);
  $files = glob($path . $pattern, $flags);
  foreach ($paths as $path) {
  $files = array_merge($files, $this->rglob($pattern, $flags, $path));
  }
  return $files;
 }

 public function changeContents($replace , $sentence , $flags = 0, $path = '') {
 $all = $this->rglob($this->getExt() , $flags, $path);
 foreach ($all as $file) {

  $filename = $file;
  $handle = fopen($filename, "r");
  $contents = fread($handle, filesize($filename));
  fclose($handle);
  $contents = str_replace($replace , $sentence, $contents);

  if (is_writable($filename)) {
   if (!$handle = fopen($filename, 'w+')) {
    echo "Cannot open file ($filename)
";
    exit;
   }

   // Write $contents to our opened file.
   if (fwrite($handle, $contents) === FALSE) {
    echo "Cannot write to file ($filename)
";
    exit;
   }

   echo "Success, wrote content to file ($filename)
";

   fclose($handle);
  } else {
   echo "The file $filename is not writable
";
  }
 }
 }}