Php bir dosyayı okurken bellek kurtarmak için nasıl?

6 Cevap php

Ben birden fazla sayfa kullanmak, ne bir 200kb dosya var, ama her sayfada bu yüzden nasıl ben satır numarasını biliyorsanız ben gerekenler sadece bu satırları okuyabilir sadece o dosyanın 1-2 satır gerekir?

Ben sadece 10 satır gerekiyorsa Örneğin, ben `t bellekteki tüm satırları, sadece 10 hat yük istemiyorum.

Benim kötü İngilizce için üzgünüm!

6 Cevap

Eğer çizgi ofset biliyorum sürece, o noktaya kadar her satırını okumak gerekir. Sadece fgets() gibi bir şey ile dosyaya döngü ile (siz istemediğiniz) eski satırları atmak olabilir. (EDIT: yerine fgets(), ben öneririm @Gordon 's solution)

Muhtemelen daha iyi bir çözüm veritabanı motoru dizeleri depolamak homurtu iş yapacak ve size izin olarak (çok verimli) Bu ile bir çizgi ama bir rekor olmaz (belirli bir "hat" olsun, bir veritabanını kullanmak olacaktır bir sayısal kimlik, ancak ondan önce kayıtlarını okumak zorunda kalmadan aynı şey) tutarındadır.

Try SplFileObject

echo memory_get_usage(), PHP_EOL;        // 333200

$file = new SplFileObject('bible.txt');  // 996kb
$file->seek(5000);                       // jump to line 5000 (zero-based)
echo $file->current(), PHP_EOL;          // output current line 

echo memory_get_usage(), PHP_EOL;        // 342984 vs 3319864 when using file()

Geçerli satırı çıktısı için, current() ya da sadece echo $file kullanabilir ya. Ben bunu daha net olsa yöntemini kullanmak bulabilirsiniz. Ayrıca fgets() kullanabilirsiniz, ancak bu sonraki hat almak istiyorum.

Tabii ki, sadece ortadaki üç satır gerekir. Ben memory_get_usage sadece bu yaklaşım neredeyse hiç bellek yemiyor kanıtlamak için çağırır ekledik.

Dosyanın içeriği değişir mi? Statik, ya da nispeten statik ise, size veri okumak istiyorum uzaklıklar bir listesini oluşturabilirsiniz. Örneğin, dosya yılda bir kez değişir, ama bunu kat günde yüzlerce okuyun, sonra istediğiniz çizgilerin uzaklıklar önceden hesaplamak ve doğrudan bu gibi onlara atlamak eğer:

 $offsets = array();
 while ($line = fread($filehandle)) { .... find line 10 .... }
 $offsets[10] = ftell($filehandle); // store line 10's location
 .... find next line
 $offsets[20] = ftell($filehandle);

ve benzerleri. Daha sonra, trivially böyle o çizginin yere atlayabilirsiniz:

 $fh = fopen('file.txt', 'rb');
 fseek($fh, $offsets[20]); // jump to line 20

Ama bu tamamen overkill olabilir. Işlemleri kıyaslama deneyin - precompute / atlamadan karşı "20 satırları okurken" Oldfashioned yapmak için ne kadar sürer karşılaştırın.

Depolama olmadan içlerinden sadece döngü, örneğin

$i = 1;
$file = fopen('file.txt', 'r');
while (!feof($file)) {
   $line = fgets($file); // this gets whole line from the file;
   if ($i == 10) {
       break; // break on tenth line
   } 
   $i ++;
}

Yukarıdaki örnek bu dosyadan aldım sadece son satır için bellek tutmak istiyorum, bu yüzden bunu yapmak için en bellek verimli yoludur.

kullanmak fgets(). Bu durumda bellekte 10 çizgileri saklamak olmaz :-) 10 kez

Neden sadece ilk on satır yüklemeye çalışıyorsun? Eğer tüm bu satırları yüklenirken aslında bir sorun olduğunu biliyor musunuz?

Eğer ölçülen değil varsa, o zaman bir sorun olduğunu bilmiyorum. Olmayan sorunlar için optimize zaman kaybetmeyin. Şansını bu dosyayı yüklerken gerçekten bir darboğaz olduğu bir gerçeği biliyorum sürece tüm 200K dosyası yüklenirken değil sahip olacak herhangi bir performans değişikliği algılanamaz olacağını vardır.