Bir metin dosyası başından hatları X numarasını silmek için PHP nasıl kullanılır

6 Cevap php

Ben bir PHP komut dosyası yazıyorum ve komut gerçekleştirdiği operasyonların basit bir metin dosyası giriş çıkışları. Nasıl belli bir dosya boyutu ulaştığında bu dosyadan ilk birkaç satır silmek için PHP kullanmak istiyorsunuz?

İdeal olarak, ilk iki satır (tarih / zaman oluşturulan ve boş) tutmak ve çizgi 3 silme işlemini başlatmak ve çizgilerin X miktarda silmek için bunu istiyorum. Ben zaten dosya boyutu () işlevi hakkında biliyorum, bu yüzden dosya boyutunu denetlemek için bu kullanarak olacak.

Örnek günlüğü metin:

*** LOG FILE CREATED ON 2008-10-18 AT 03:06:29 ***

2008-10-18 @ 03:06:29  CREATED: gallery/thumbs
2008-10-18 @ 03:08:03  RENAMED: gallery/IMG_9423.JPG to gallery/IMG_9423.jpg
2008-10-18 @ 03:08:03  RENAMED: gallery/IMG_9188.JPG to gallery/IMG_9188.jpg
2008-10-18 @ 03:08:03  RENAMED: gallery/IMG_9236.JPG to gallery/IMG_9236.jpg
2008-10-18 @ 03:08:03  RENAMED: gallery/IMG_9228.JPG to gallery/IMG_9228.jpg
2008-10-18 @ 03:08:03  RENAMED: gallery/IMG_3104.JPG to gallery/IMG_3104.jpg
2008-10-18 @ 03:08:03  RENAMED: gallery/First dance02.JPG to gallery/First dance02.jpg
2008-10-18 @ 03:08:03  RENAMED: gallery/BandG02.JPG to gallery/BandG02.jpg
2008-10-18 @ 03:08:03  RENAMED: gallery/official03.JPG to gallery/official03.jpg
2008-10-18 @ 03:08:03  RENAMED: gallery/Wedding32.JPG to gallery/Wedding32.jpg
2008-10-18 @ 03:08:03  RENAMED: gallery/Gettaway car16.JPG to gallery/Gettaway car16.jpg
2008-10-18 @ 03:08:04  CREATED: gallery/thumbs/Afterparty05.jpg
2008-10-18 @ 03:08:04  CREATED: gallery/thumbs/IMG_9254.jpg
2008-10-18 @ 03:08:04  CREATED: gallery/thumbs/IMG_9175.jpg
2008-10-18 @ 03:08:04  CREATED: gallery/thumbs/official05.jpg
2008-10-18 @ 03:08:04  CREATED: gallery/thumbs/First dance01.jpg
2008-10-18 @ 03:08:04  CREATED: gallery/thumbs/Wedding29.jpg
2008-10-18 @ 03:08:04  CREATED: gallery/thumbs/men walking.jpg

6 Cevap

Use the SPL, Luke

PHP 5 Yineleyicilerde iyilik bol gelir:

<?php

$line_to_strip = 5;
$new_file = new SplFileObject('test2.log', 'w');

foreach (new LimitIterator(new SplFileObject('test.log'), $line_to_strip) as $line)
    $new_file->fwrite($line);    

?>

Bu fopen ile karıştırmasını yaparken ne yapabilirim, bu bellekte bir seferde sadece tek bir satır tüm dosya tutmaz ve onu takın ve tam OO beri her yerde deseni yeniden ki temiz.

Daha sonra ilk olarak X satırları kaldırmak için array_slice() kullanmak, çizgilerin bir diziye dosyasını okumak için file() işlevini kullanabilirsiniz.

$X = 100; // Number of lines to remove

$lines = file('log.txt');
$first_line = $lines[0];
$lines = array_slice($lines, $X + 2);
$lines = array_merge(array($first_line, "\n"), $lines);

// Write to file
$file = fopen('log.txt', 'w');
fwrite($file, implode('', $lines));
fclose($file);

Bu günlük dosyaları bir metin-kitap sorundur ve ben başka bir çözüm önermek istiyorum.

Yaklaşım "dosyalarının başında çıkarmadan hatları" ile sorun o yazıyor her yeni hatlar için ilk satırları kaldırmak zorundadır kez yeni hatlar ekleyerek, son derece yavaş olur olmasıdır.

Ekleme Normal günlük dosyası (- neden genellikle log dosyaları bu geniş parçalanma sonuçları yeni bir sektör, tahsis varken bir ve bir kez) dosya sisteminde dosyanın sonunda birkaç bayt yazma içerir.

Eğer yazılmış her satır için başında bir çizgi çıkarılırken ama burada büyük bir sorundur. Tüm dosya belleğe ilk okunacak ve ardından (comparision) sabitdisk I / O büyük kestirmeniz sonuçlanan yeniden yazılması gerekir. Daha da kötüsü, burada "PHP dizi ayrılır ve ilk satırları atlamak" çözümleri, PHP dizilerin doğasına son derece yavaştır. Log dosya boyutu limiti çok küçük ya da unoften için yazılmış ise, ancak (log dosyaları ile olduğu gibi) yazıyor bir sürü, aynı dev operasyon bir çok kez yapılması gereken varsa, bu bir sorun değil önemli performans sakıncaları ile sonuçlanır.

Bu 50 için alan bir çizgi üzerinde park araba olarak hayal edilebilir. Ilk 50 araba park sadece infront arabanın arkasında sürücü ve bitmiş, hızlıdır. Eğer 50 gelir ve önünde araç (dosyanın başlangıcı) kaldırılması gerekir ama ne zaman sen ile sürücü önce böylece 2. 3. ve 1'st konumu ile 2'nd araba var 50'th pozisyon son araba. (Ve bu park etmek istiyorum every yeni bir araba için yinelenmesi gerekir!)

Benim önerim dosyalar yerine, DATEwise log farklılaştıran tasarrufu, ve sonra Böylece zaten çok iyi bu sorunu çözmüştür dosya sistemi, yararlanarak geri vb 30 gün süre saklamanız.

Eğer bir linux komutu çalıştırmak, denemek split. Bu şeyleri kolaylaştırmak için satır sayısı ile split sağlar.

Aksi takdirde, ben okudum ve 2 diğer dosyalara yazmak gerekir düşünüyorum.

Alternatif @Greg's cevap, sen, bir diziye tüm dosyasında okumak ilk X sayıda girişleri atlamak, daha sonra dosyaya dizi yazabilirsiniz.

Bir yaklaşım olarak: http://us3.php.net/manual/en/function.file-get-contents.php

$fle = file_get_contents("filename");
// skip X many newlines, overwriting the contents of the string with ""
// http://us3.php.net/manual/en/function.file-put-contents.php
file_put_contents("filename", $fle);

Tipik işletim sistemleri "yerinde" bir dosyanın içeriğini eklemek veya silmek için yeteneği vermeyin. Ne yapmak gerekir ilk dosyayı okur bir fonksiyon yazmak ve saklamak istediğiniz satırları içeren bir new çıktı dosyasını oluşturur. İşiniz bittiğinde, sonra eski dosyayı silin ve eski adı yeni birini yeniden adlandırın.

Pseudocode:

open original file IN for reading
create new output file OUT
read the first two lines from IN
write these lines to OUT
for each line to skip:
    read a line from IN
for the remainder of the file:
    read a line from IN
    write the line to OUT
close IN
close OUT
delete IN
rename OUT to IN

Sunulan diğer bazılarını üzerinde bu yöntemin avantajı doesn't ilk belleğe tüm dosyayı okumak için ihtiyaç olmasıdır. Eğer üst boyut sınırı ne kadar büyük söz etmedi, ancak 100 MB gibi bir şey eğer belleğe dosya yükleme alanı kabul edilebilir bir kullanım olmadığını bulabilirsiniz.