![]() |
![]() ![]() |
![]() |
![]() ![]()
Post
#1
|
|
Grupa: Zarejestrowani Postów: 243 Pomógł: 1 Dołączył: 1.06.2010 Ostrzeżenie: (0%) ![]() ![]() |
Mam plik baza.txt, który waży 45 MB i chcę z niego odczytać 100 linii zawrtości zaczynając odczyt od linii onumerze 10000.
Jakiej funkcji użyć do odczytu i jak czytać ? Dodam tylko, że file() deklaruje mi tyle pamięci, że nie da się załadować tak dużego pliku do pamięci . |
|
|
![]()
Post
#2
|
|
![]() Grupa: Moderatorzy Postów: 4 069 Pomógł: 497 Dołączył: 11.05.2007 Skąd: Warszawa ![]() |
Nie da się od linii o numerze 10000.
Zainteresuj się sqlite na przyszłość. |
|
|
![]()
Post
#3
|
|
Grupa: Zarejestrowani Postów: 590 Pomógł: 107 Dołączył: 25.10.2011 Ostrzeżenie: (0%) ![]() ![]() |
Możesz to zrobić, ale weź pod uwagę, że jeśli chcesz robić to co chwilę, to będzie to strasznie nieefektywne i dobijające system. Zainteresuj się funkcjami: fopen i fread.
Idea jest prosta: 1. poprzez fopen otwierasz plik w trybie do odczytu 2. w pętli odczytujesz kolejne linie (i nie zapisujesz ich nigdzie!!!), których będzie u Ciebie 9999. 3. Wewnętrzny wskaźnik pliku stoi na linii 10000. 4. Czytasz linię i zachowujesz 5. punkt 4 powtarzasz tak długo, jak długo potrzebujesz 6. Zamykasz plik Ale fakt faktem, Spawnm ma rację: jakaś baza SQL by się już bardzo przydała, choćby sqlite. |
|
|
![]()
Post
#4
|
|
Grupa: Zarejestrowani Postów: 1 332 Pomógł: 294 Dołączył: 12.10.2008 Skąd: Olkusz Ostrzeżenie: (0%) ![]() ![]() |
Nie da się od linii o numerze 10000. Zainteresuj się sqlite na przyszłość. wiem, że żartowałeś by nie podać starej funkcji gdzie przy tamtym podejściu też można złe nawyki sobie wyrobić, też jej nie podam choć łatwo jej nazwę będzie wywnioskować co ją się stosuje do uchwytu pliku... po za tym jakoś SQLite też jest moim faworytem... Z biblioteki SPL klasa SplFileObject metody: SplFileObject::seek(int) SplFileObject::fgets() | SplFileObject::current() znajomość i umiejętne zastosowanie tych funkcji pozwala na szybie wrzucenie danych do bazy przy minimalnym zużyciu pamięci... dodatkowo jeśli chodzi o odczyt baaaaardzo dużych plików XML to hasło do google "SAX PHP" - choć mógłbym dać klasę w dokumentacji PHP ale masz też hasło na przykłady - jednak by dobrze wykorzystać ją poprogramuj se paradoksalnie w JavaScript by umiejętnie stosować technikę programowania zdarzeniowego lub w C++ a dokładniej w bibliotece QT // EDIT nie odświeżyłem sobie i widzę, że dostałeś linka do tych funkcji ;p // edit 2 a jednak nie - po staremu to fgets (pobiera linię pliku i przewija wskaźnik dalej - ale skorzystaj z obiektowego podejścia i z biblioteki SPL) itd... za dużo tego dobrego miodziku ;D Ten post edytował zegarek84 2.11.2012, 21:55:03 -------------------- Jeśli twoja ręka rusza do przodu powstrzymaj swój gniew; gdy wyprzedza cię twój gniew - wycofaj rękę.
|
|
|
![]() ![]()
Post
#5
|
|
Grupa: Zarejestrowani Postów: 243 Pomógł: 1 Dołączył: 1.06.2010 Ostrzeżenie: (0%) ![]() ![]() |
wygenerowałem dla testów plik z 1500000 linii kodu.
odczytuję to tak : <?php $file = new SplFileObject('baza.txt'); for($i=1000000;$i<=1000200;$i++){ $file->seek($i); echo $file->current().'<br>'; } ?> [/php] i działa za wolno ![]() Ten post edytował fiasko 2.11.2012, 22:23:24 |
|
|
![]()
Post
#6
|
|
Grupa: Zarejestrowani Postów: 1 332 Pomógł: 294 Dołączył: 12.10.2008 Skąd: Olkusz Ostrzeżenie: (0%) ![]() ![]() |
przewinięcie do tak dużego pliku gdzie są nie regularne długości wersów trochę potrwa - 1 milion pomijając inne warunki to co najmniej sprawdzenie i zliczenie miliona znaków "\n" co musi minimalnie zająć pół sekundy (plus porównanie innych znaków) - w końcu patrzysz od początku pliku... tą techniką którą Ci wskazałem jesteś w stanie odczytywać baaaardzo duże pliki dosyć wydajnie - całość możesz wrzucić do jakiejkolwiek bazy danych, choćby płaskiej bazy danych jak SQLite gdzie każdy wiersz możesz mieć zindeksowany i dostęp do poszczególnych wierszy będzie szybszy...
ps. przecież interesowały Cię wielkości 100 razy mniejsze ;p - 10000 to nie to samo co milion ;D Ten post edytował zegarek84 2.11.2012, 22:38:30 -------------------- Jeśli twoja ręka rusza do przodu powstrzymaj swój gniew; gdy wyprzedza cię twój gniew - wycofaj rękę.
|
|
|
![]() ![]()
Post
#7
|
|
Grupa: Zarejestrowani Postów: 243 Pomógł: 1 Dołączył: 1.06.2010 Ostrzeżenie: (0%) ![]() ![]() |
interesują mnie jeszcze większe bo będę dostawać pliki z 50 mln linii
![]() Na bazie nie będę z tym pracować bo musiałbym pracować na setkach tabel. Tu będzie tak, że przerobiony plik nie będzie mi już potrzebny. ok teraz jest idealnie ![]()
Ten post edytował fiasko 2.11.2012, 23:03:18 |
|
|
![]()
Post
#8
|
|
Grupa: Zarejestrowani Postów: 1 332 Pomógł: 294 Dołączył: 12.10.2008 Skąd: Olkusz Ostrzeżenie: (0%) ![]() ![]() |
interesują mnie jeszcze większe bo będę dostawać pliki z 50 mln linii ![]() Na bazie nie będę z tym pracować bo musiałbym pracować na setkach tabel. Tu będzie tak, że przerobiony plik nie będzie mi już potrzebny. gdyby długość linii była stała można by to zrobić optymalniej, ale pomińmy tą kwestię (w końcu nie będziemy tu implementować bazy danych ;p)... wspomniałeś, że to co obrobione to nie potrzebne i będziesz miał to na zasadzie kolejki... więc by następnym razem nie przewijać pliku tak daleko przy nieregularnych liniach to nie mógłbyś tą techniką pociąć ten plik na wiele mniejszych po te 10000 linii kodu?? i w myśl zasady 100|1000 plików na katalog (nie pamiętam jaka liczba była optymalna) - więc musiałbyś sobie jakiś system nazewnictwa wystosować - obrobisz to to to usuwasz i tniesz następny plik... a przy kolejnej kolejce nie musisz tak daleko przewijać - to tylko propozycja... //edit czyli fseek przewijało za każdym razem od początku pliku - zaczynałem pisać w poprzednim poście, byś korzystał z fseek raz a potem z fgets (miks current i next ^^) ale zaraz to skasowałem bo zdawało mi się to niedorzeczne ;p - a już jakiś czas nie miałem potrzeby obróbki duuuużych plików ;p Ten post edytował zegarek84 2.11.2012, 23:12:15 -------------------- Jeśli twoja ręka rusza do przodu powstrzymaj swój gniew; gdy wyprzedza cię twój gniew - wycofaj rękę.
|
|
|
![]()
Post
#9
|
|
![]() Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
Wygląda na to, że masz do obrobienia duży plik i z jakiegoś powodu uznałeś, że lepszym rozwiązaniem będzie robienie tego "po trochu, co chwilę" (cron) zamiast za jednym razem - dlaczego?
|
|
|
![]()
Post
#10
|
|
Grupa: Zarejestrowani Postów: 1 332 Pomógł: 294 Dołączył: 12.10.2008 Skąd: Olkusz Ostrzeżenie: (0%) ![]() ![]() |
w sumie też dobre pytanie, chyba, że nie ma dostępu ko konsoli ;] - w konsoli ma się znacznie mniejsze ograniczenia, a najważniejsze to to czasowe ;]... wspomniał o obiektach zserializowanych - po drodze może mieć jeszcze multum operacji... raz miałem też nietypowy problem oprócz tego, iż pliki XML były duże, ale nie mogłem mieć pewności, czy dane w bazie znajdują się, no i po swojemu musiałem implementować "iloraz"|"iloczyn" na bazie - już tych "fachowych" określeń|nazw nie jestem pewien ;p... w każdym bądź razie techniki programowania zdarzeniowego to potężne narzędzie optymalizacyjne w dowolnym języku ;D
Ten post edytował zegarek84 2.11.2012, 23:40:07 -------------------- Jeśli twoja ręka rusza do przodu powstrzymaj swój gniew; gdy wyprzedza cię twój gniew - wycofaj rękę.
|
|
|
![]() ![]()
Post
#11
|
|
Grupa: Zarejestrowani Postów: 243 Pomógł: 1 Dołączył: 1.06.2010 Ostrzeżenie: (0%) ![]() ![]() |
Będę wykonywać operacje na obiektach, które w ścisłej kolejności zostały wygenerowane do pliku. Obiektami są dane przefiltrowane pod różnym kontem. Każdy taki plik stanowi unikalną kolejkę zadań na której pracuje moja aplikacja.
Zwyczaje musiałem wygenerować kolejkę zadań według której pracują procesy CRON. Wcześniej pracowałem na bazie i nie byłem wstanie zapisać 5 mln rekordów zanim nie przekroczę limitu czasu serwera na wykonanie skryptu. Wpadłem więc na pomysł aby agregować te dane w zmiennej i zapisać na koniec do jednego pliku. W sumie mógłbym trzymać w bazie tego typu rzeczy, ale za jakiś czas nie wyobrażałbym sobie wielkości bazy ![]() Dzięki temu teraz będę mógł szybko pracować na tych obiektach zgodnie z oczekiwaną kolejnością. |
|
|
![]()
Post
#12
|
|
Grupa: Zarejestrowani Postów: 1 332 Pomógł: 294 Dołączył: 12.10.2008 Skąd: Olkusz Ostrzeżenie: (0%) ![]() ![]() |
Wcześniej pracowałem na bazie i nie byłem wstanie zapisać 5 mln rekordów zanim nie przekroczę limitu czasu serwera na wykonanie skryptu. jeśli obrabiasz duże ilości danych to nie prościej wykupić jakiś najtańszy VPS byś miał dostęp do PHP spod konsoli?? nie miałbyś takich limitów czasowych - ale fakt, przynajmniej spojrzałeś innym okiem by zrobić to optymalniej... lub te dane mógłbyś obrabiać na lokalnej maszynie a dopiero potem wyniki przesłać na serwer... Wpadłem więc na pomysł aby agregować te dane w zmiennej i zapisać na koniec do jednego pliku. co to znaczy, że agregujesz dane w zmiennej?? czy te dane są przyrostowe i zwiększają tą zmienną z upływem czasu?? tzn. potrzebna pamięć skryptu rośnie stale zapewne... czemu danych nie zapisujesz na bieżąco do pliku linia po linii?? SplFileObject::fwrite, a plik otwórz z modyfikatorem "a"... swoją drogą trochę interesowałem się strumieniowymi bazami danych (nastawionymi na określone zdarzenia) i gdyby nie brak czasu to miałem pisać prostą implementację na swoje potrzeby bez implementacji języka SQL, z tym, że to raczej Cię nie interesuje gdyż to już programowanie sieciowe ;] -------------------- Jeśli twoja ręka rusza do przodu powstrzymaj swój gniew; gdy wyprzedza cię twój gniew - wycofaj rękę.
|
|
|
![]()
Post
#13
|
|
![]() Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
A nie możesz po prostu wyłączyć limitu czasu wykonywania skryptu? (patrz: set_time_limit)
Nie mniej jednak, jeżeli już przetwarzasz ten plik w porcjach przy użyciu CRON-a, możesz w jakimś pomocniczym pliku zapisać sobie informację o tym ile już rekordów (zserializowanych obiektów) przetworzyłeś oraz ile bajtów zajmowały one w pliku. Dzięki temu przy ponownym uruchomieniu skryptu będziesz mógł natychmiast przeskoczyć w odpowiednie miejsce (fseek/SplFileObject::fseek). Ten post edytował Crozin 3.11.2012, 02:47:52 |
|
|
![]()
Post
#14
|
|
Grupa: Zarejestrowani Postów: 1 332 Pomógł: 294 Dołączył: 12.10.2008 Skąd: Olkusz Ostrzeżenie: (0%) ![]() ![]() |
co racja to racja, będzie szybciej, ale liczyć nie musi
SplFileObject::ftell - Returns the position of the file pointer which represents the current offset in the file stream. analogiczna funkcja do proceduralnego uchwytu ftell -------------------- Jeśli twoja ręka rusza do przodu powstrzymaj swój gniew; gdy wyprzedza cię twój gniew - wycofaj rękę.
|
|
|
![]() ![]() |
![]() |
Wersja Lo-Fi | Aktualny czas: 25.04.2025 - 05:35 |