2008-10-02 13 views
19

fopen kończy się niepowodzeniem, gdy próbuję odczytać w pliku o bardzo umiarkowanym rozmiarze w PHP. A 6 meg file sprawia, że ​​się dusi, choć mniejsze pliki około 100k są w porządku. Czytałem, że czasami konieczna jest ponowna kompilacja PHP z flagą -D_FILE_OFFSET_BITS=64 w celu odczytania plików z ponad 20 koncertów lub coś niedorzecznego, ale czy nie powinienem mieć problemów z plikiem 6 megapikselowym? W końcu będziemy chcieli czytać pliki o wielkości około 100 meg, i byłoby mi miło móc je otworzyć, a następnie odczytać je wiersz po wierszu za pomocą fgetów, tak jak w przypadku mniejszych plików.Czytanie bardzo dużych plików w PHP

Jakie są twoje sztuczki/rozwiązania do czytania i wykonywania operacji na bardzo dużych plikach w PHP?

Aktualizacja: Oto przykład prostego bloku kodu, który zawodzi w moim pliku 6 megaplików - PHP nie wydaje się zgłaszać błędu, po prostu zwraca wartość false. Może robię coś wyjątkowo głupiego?

$rawfile = "mediumfile.csv"; 

if($file = fopen($rawfile, "r")){ 
    fclose($file); 
} else { 
    echo "fail!"; 
} 

Kolejna zmiana: Dzięki wszystkim za pomoc, to nie okazać się coś niewiarygodnie głupiego - problem uprawnienia. Mój mały plik miał niewytłumaczalnie uprawnienia do odczytu, gdy większy plik nie był. Doh!

+0

Są po prostu stara się przekazać plik thru? to znaczy. Pobieranie? A może w jakimś celu analizujesz dane w plikach? Dzięki. – DreamWerx

+0

to nie powinno zawieść bez generowania ostrzeżenia/błędu. Proszę włączyć wszystkie błędy za pomocą error_reporting (E_ALL) i upewnić się, że display_errors są włączone, aby wyświetlały się w przeglądarce, lub sprawdź dziennik błędów serwera. –

Odpowiedz

36

Czy jesteś pewien, że to fopen że jest zepsuty i nie Ustawianie limitu czasu skryptu? Wartość domyślna wynosi zwykle około 30 sekund, a jeśli pobieranie pliku trwa dłużej, może to być przyczyną potknięcia.

Inną kwestią, którą należy wziąć pod uwagę, może być ograniczenie pamięci skryptu - odczytanie pliku do tablicy może spowodować potknięcie się o to, dlatego należy sprawdzić dziennik błędów pod kątem ostrzeżeń dotyczących pamięci.

Jeśli żaden z powyższych problemów nie stanowi problemu, możesz zapoznać się z plikiem fgets, aby odczytać plik wiersz po wierszu i kontynuować przetwarzanie.

$handle = fopen("/tmp/uploadfile.txt", "r") or die("Couldn't get handle"); 
if ($handle) { 
    while (!feof($handle)) { 
     $buffer = fgets($handle, 4096); 
     // Process buffer here.. 
    } 
    fclose($handle); 
} 

Edit

PHP wydaje się nie rzucać się błąd, to po prostu zwraca false.

Czy ścieżka do $rawfile jest poprawna w stosunku do miejsca, w którym uruchomiony jest skrypt? Być może spróbuj tu ustawić bezwzględną ścieżkę dla nazwy pliku.

+3

Możliwe jest tylko rozwiązanie otwierania naprawdę dużych plików. Przetwarzam przez to rozwiązanie 1,5 GB pliku bez problemu. Wszystkie inne rozwiązania, takie jak file_get_contents z pliku, będą czytać cały plik do pamięci. To podejście polega na przetwarzaniu linii po linii. – StanleyD

+0

Dlaczego 4096 oznacza jedną linię? – Phoenix

+0

@Phoenix 4096 oznacza, odczyt co najwyżej 4096 - 1 bajty iff nie napotkano żadnych podziałów linii. Sprawdź instrukcję. – a3f

0

Cóż, możesz spróbować użyć funkcji readfile, jeśli chcesz wydrukować plik.

Jeśli tak nie jest - może powinieneś pomyśleć o projekcie aplikacji, dlaczego chcesz otwierać tak duże pliki na żądanie internetowe?

+0

Musimy zautomatyzować dodawanie dużych zbiorów danych, dzięki czemu duże pliki CSV mogą być przesyłane przez użytkownika i są przetwarzane i integrowane z bazą danych przez aplikację. Chciałbym, aby inne sugestie dotyczące podejścia, jeśli myślisz, że czytanie i parsowanie przesłanych plików za pomocą PHP nie jest najlepszym rozwiązaniem. –

+0

Nie sądzę, że PHP miałoby problem z plikami CSV o pojemności 6 MB? Wygląda na to, że jest wystarczająco mały, aby mógł sobie z nim poradzić. Zgodnie z powyższymi komentarzami, proszę podać dokładny błąd/i/lub kod. Czy może to być błąd związany z pamięcią? Lub max_execution_time? Potrzebujemy więcej informacji, aby pomóc. – DreamWerx

1

Użyłem fopen do otwierania plików wideo do przesyłania strumieniowego, używając skryptu php jako serwera strumieniowego przesyłania wideo, i nie miałem problemu z plikami o rozmiarze większym niż 50/60 MB.

0

Jeśli problem wynika z przekroczenia limitu pamięci, możesz spróbować ustawić wyższą wartość (może to działać lub nie, zależnie od konfiguracji php).

ta ustawia limit pamięci do 12 MB

ini\_set("memory_limit","12M"); 
+2

Uwaga: Chociaż może to pomóc, to tylko odkłada problem: gdy pojawi się plik 15 MB w, problem wraca. (Jeśli twoje pliki nigdy nie przekroczą określonego limitu, może to spowodować, że problem zniknie). – Piskvor

0

dla mnie, fopen() jest bardzo powolny z plikami ponad 1MB, plik() jest znacznie szybsze. Po prostu próbuje czytać linie 100 na raz i tworzyć wsadowe wstawki, fopen() trwa 37 sekund w stosunku do pliku() zajmuje 4 sekundy. Musi to być ciąg znaków-> krok tablicy wbudowany w plik()

Chciałbym wypróbować wszystkie opcje obsługi plików, aby zobaczyć, które najlepiej sprawdzą się w twojej aplikacji.

5

Czy 2 testy z pliku 1.3GB i 9.5GF Plik

1,3

Korzystanie fopen()

Proces ten stosowany 15555 ms dla swoich obliczeń.

To spędził 169 ms w systemie nazywa

Korzystanie file()

Proces ten wykorzystywany 6983 ms dla swoich obliczeń.

To spędził 4469 ms w systemie nazywa

9.5GB

Korzystanie fopen()

Proces ten wykorzystywany 113559 ms dla swoich obliczeń

wydano 2532 ms w systemie nazywa

Używanie file()

Proces ten wykorzystywany 8221 ms dla swoich obliczeń

spędził on 7998 ms w system wywołuje

Wydaje file() jest szybsza

Powiązane problemy