Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

> Skrypt sortujący plik
Beniooo
post
Post #1





Grupa: Zarejestrowani
Postów: 260
Pomógł: 26
Dołączył: 26.01.2012
Skąd: Ci to przyszło do głowy?

Ostrzeżenie: (0%)
-----


Witam, poszukuje skryptu kjtóry mi posortuje słowa znajdujące się w pliku tekstowym, każde słowo jest w innym wierszy, słów jest mniej niż 3 miliony, a pliczek ma rozmiar ~36MB
Dostałem od usera na forum takie coś:
  1. <?php
  2. $file = file_get_contents("slowa-win.txt");
  3. $file_lines = explode("\n", $file);
  4.  
  5.  
  6. for($i=0;$i<count($file_lines);$i++)
  7. {
  8.  
  9. $line_length[$i] = mb_strlen($file_lines[$i]);
  10. }
  11.  
  12. asort($line_length);
  13.  
  14. foreach ($line_length as $kl => $linel)
  15. {
  16. echo "$file_lines[$kl]<br>";
  17. }
  18. ?>


Niestety nie działa, wyświetla błąd "Fatal error: Allowed memory size of 25165824 bytes exhausted (tried to allocate 36854802 bytes) in C:\AppServ\www\index.php on line 6"
Ma ktos skrypt który posortuje ten plik żeby słowa były od najkrótszego do najdłuższego?
Go to the top of the page
+Quote Post
 
Start new topic
Odpowiedzi
redeemer
post
Post #2





Grupa: Zarejestrowani
Postów: 915
Pomógł: 210
Dołączył: 8.09.2009
Skąd: Tomaszów Lubelski/Wrocław

Ostrzeżenie: (0%)
-----


Dlaczego to musi być skrypt? PHP nie nadaje się do takich rzeczy jak sortowanie plików o takich wielkościach (chyba że zrzucimy to na bazę danych, ale tutaj PHP miałoby tylko rolę "odczytaj linię i wrzuć do bazy"). Zasadnicze pytanie jest takie: czy chcesz ten plik posortować, czy chcesz mieć skrypt w PHP, który Ci to posortuje?

Edit: Postanowiłem jednak się zabawić i napisać skrypt w PHP (bez udziału baz danych) oparty na plikach tymczasowych (w celu ograniczenia zużycia pamięci). Nie sortuje on jednak alfabetycznie, ale tylko po długości.
  1. <?php
  2.  
  3. $fnameIn = 'input.txt';
  4. $fnameOut = 'output.txt';
  5. $tmpFilePrefix = '/tmp/xx_length.';
  6. $chunks = 4; // how many files per one length
  7.  
  8. //@todo check if fnameIn exists
  9.  
  10. /* step 1, separate lines with same lengths into different files, they're also chunked */
  11. $f = fopen($fnameIn, 'r');
  12. $maxLength = -1;
  13. $chunkArr = array();
  14.  
  15. while(!feof($f)) {
  16. $line = fgets($f);
  17.  
  18. $lineLength = mb_strlen($line);
  19. if ($lineLength > $maxLength) {
  20. $maxLength = $lineLength;
  21. }
  22.  
  23. if (!isset($chunkArr[$lineLength])) {
  24. $chunkArr[$lineLength] = 0;
  25. //@todo clear $tmpFname file (with all chunks). When "step 2" won't remove tmp files somehow, we will have doubled content, couse of FILE_APPEND flag
  26. }
  27.  
  28. $tmpFname = $tmpFilePrefix.$lineLength.'_'.($chunkArr[$lineLength]++%$chunks);
  29. file_put_contents($tmpFname, $line, FILE_APPEND); }
  30.  
  31. fclose($f);
  32.  
  33. /* step 2, merge and delete all temporary files
  34. This may also be memory consumpting (ex. when all lines have same length and we have chunks set to 1), but in most cases should be better than sorting whole file at once
  35. */
  36.  
  37. $f = fopen($fnameOut, 'w');
  38.  
  39. for($i=0; $i<=$maxLength; $i++) {
  40.  
  41. // check all chunks
  42. for($k=0;$k<$chunks;$k++) {
  43. $tmpFname = $tmpFilePrefix.$i.'_'.$k;
  44.  
  45. if (file_exists($tmpFname)) {
  46. $content = file_get_contents($tmpFname);
  47. fputs($f, $content);
  48. unlink($tmpFname);
  49. }
  50. }
  51. }
  52.  
  53. fclose($f);

Co do samego jednorazowego posortowania to nie wiem jak pod Windowsem, ale polecenie, które zadziała pod Linuksem wkleiłem Ci w poprzednim wątku http://forum.php.pl/index.php?s=&showt...st&p=979723. Na windowsie możesz zainstalować sobie cygwin - konsola i narzędzia konsolowe z linuksa.

Ten post edytował redeemer 23.07.2012, 11:22:07
Go to the top of the page
+Quote Post

Posty w temacie


Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 17.10.2025 - 08:05