2010-08-26 35 views
14

Tôi cần một hàm giống như preg_replace nhưng thay vì chuỗi, tôi cần nó để làm việc với tệp/nội dung tệp.Thay thế nội dung tệp bằng PHP

+0

Bạn có thể kéo nội dung tệp vào một biến bằng cách lặp lại nó bằng cách sử dụng fread và sau đó làm việc với preg_replace như bạn làm với một chuỗi văn bản? – Chris

+0

Có nhưng sau đó nội dung cập nhật phải được ghi vào các tệp được lấy từ đó. –

+0

Vì vậy, vấn đề để viết nội dung trở lại tập tin là gì? –

Trả lời

40

Bạn có thể làm:

$file = 'filename'; 
file_put_contents($file,str_replace('find','replace',file_get_contents($file))); 
19

@ câu trả lời codaddict là khá sufficent cho các tập tin nhỏ (và sẽ là thế nào tôi sẽ thực hiện nó nếu kích thước của tập tin là dưới một MiB). Tuy nhiên nó sẽ ăn một tấn bộ nhớ, và như vậy bạn nên cẩn thận khi đọc các tệp lớn.

Nếu bạn muốn có một phiên bản bộ nhớ thân thiện nhiều hơn nữa, bạn có thể sử dụng stream filters ...

class ReplaceText_filter extends php_user_filter { 
    protected $search = ''; 
    protected $replace = ''; 

    public function filter($in, $out, &$consumed, $closing) { 
     while ($bucket = stream_bucket_make_writable($in)) { 
      $bucket->data = str_replace(
       $this->search, 
       $this->replace, 
       $bucket->data 
      ); 
      $consumed += $bucket->datalen; 
      stream_bucket_append($out, $bucket); 
     } 
     return PSFS_PASS_ON; 
    } 

    public function onCreate() { 
     if (strpos($this->filtername, '.') === false) return false; 
     list ($name, $arguments) = explode('.', $this->filtername, 2); 
     $replace = ''; 
     $search = $arguments; 
     if (strpos($arguments, '|') !== false) { 
      list ($search, $replace) = explode('|', $arguments, 2); 
     } 
     if (strpos($search, ',') !== false) { 
      $search = explode(',', $search); 
     } 
     if (strpos($replace, ',') !== false) { 
      $search = explode(',', $replace); 
     } 
     $this->search = $search; 
     $this->replace = $replace; 
    } 
} 
stream_filter_register('replacetext.*', 'ReplaceText_Filter'); 

Vì vậy, sau đó bạn có thể thêm một bộ lọc dòng tùy ý. Tên của bộ lọc xác định các đối số:

$search = 'foo'; 
$replace = 'bar'; 
$name = 'replacetext.'.$search.'|'.$replace; 
stream_filter_append($stream, $name); 

hoặc cho mảng,

$search = array('foo', 'bar'); 
$replace = array('bar', 'baz'); 
$name = 'replacetext.'.implode(',', $search).'|'.implode(',', $replace); 
stream_filter_append($stream, $name); 

Rõ ràng đây là một ví dụ thực sự đơn giản (và không làm rất nhiều kiểm tra lỗi), nhưng nó cho phép bạn làm một cái gì đó như thế này:

$f1 = fopen('mysourcefile', 'r'); 
$f2 = fopen('mytmpfile', 'w'); 
$search = array('foo', 'bar'); 
$replace = array('bar', 'baz'); 
$name = 'replacetext.'.implode(',', $search).'|'.implode(',', $replace); 
stream_filter_append($f1, $name); 
stream_copy_to_stream($f1, $f2); 
fclose($f1); 
fclose($f2); 
rename('mytmpfile', 'mysourcefile'); 

Và đó sẽ tiếp tục sử dụng bộ nhớ rất thấp trong khi chế biến tiềm năng khổng lồ file (GiB hoặc TiB) ...

Ồ, và điều thú vị khác là nó có thể chỉnh sửa nội dòng các loại luồng khác nhau. Ý tôi là, bạn có thể đọc từ luồng HTTP, chỉnh sửa nội tuyến và ghi vào luồng tệp. Nó khá mạnh mẽ (vì bạn có thể chuỗi các bộ lọc này) ...

+0

Vấn đề duy nhất với câu trả lời này là khi các cụm từ tìm kiếm được đặt trên các nhóm, đặc biệt là khi xử lý các tệp lớn hơn 8 KiB. – bit2shift

Các vấn đề liên quan