Czy chcesz oznaczyć jako odpowiedź na którekolwiek z poniższych pytań?
Kim Stacks
Odpowiedzi:
684
Możesz użyć tej fgets()funkcji do odczytania pliku linia po linii:
$handle = fopen("inputfile.txt","r");if($handle){while(($line = fgets($handle))!==false){// process the line read.}
fclose($handle);}else{// error opening the file.}
Jak działa to konto dla too large to open in memoryczęści?
Starx,
64
Nie czytasz całego pliku w pamięci. Maksymalna pamięć potrzebna do uruchomienia tego zależy od najdłuższej linii na wejściu.
codaddict
13
@Brandin - Moot - W takich sytuacjach zadane pytanie, które polega na odczytaniu pliku LINE BY LINE, nie ma dobrze określonego wyniku.
ToolmakerSteve
3
@ToolmakerSteve Następnie określ, co powinno się stać. Jeśli chcesz, możesz po prostu wydrukować komunikat „Zbyt długa linia; rezygnacja”. i jest to również dobrze określony wynik.
Brandin
2
Czy wiersz może zawierać wartość logiczną false? Jeśli tak, to ta metoda zatrzyma się bez osiągnięcia końca pliku. Przykład nr 1 na tym adresie php.net/manual/en/function.fgets.php sugeruje, że fgets mogą czasami zwracać wartość logiczną false, nawet jeśli nie osiągnięto jeszcze końca pliku. W sekcji komentarzy na tej stronie ludzie zgłaszają, że fgets () nie zawsze zwraca poprawne wartości, więc bezpieczniej jest używać feof jako pętli warunkowej.
cjohansson,
130
if($file = fopen("file.txt","r")){while(!feof($file)){
$line = fgets($file);# do same stuff with the $line}
fclose($file);}
Jak powiedział @ Cuse70 w swojej odpowiedzi, doprowadzi to do nieskończonej pętli, jeśli plik nie istnieje lub nie można go otworzyć. Przetestuj if($file)przed pętlą while
FrancescoMM
10
Wiem, że to jest stare, ale: nie zaleca się używania while (! Feof ($ file)). Spójrz tutaj.
Kevin Van Ryckegem
BTW: „Jeśli we wskaźniku pliku nie ma więcej danych do odczytania, zwracana jest wartość FAŁSZ.” php.net/manual/en/function.fgets.php ... Na wszelki wypadek
<?php
$file =newSplFileObject("file.txt");// Loop until we reach the end of the file.while(!$file->eof()){// Echo one line from the file.
echo $file->fgets();}// Unset the file to call __destruct(), closing the file handle.
$file =null;
znacznie czystsze rozwiązanie. dzięki;) jeszcze nie korzystałem z tej klasy, jest tu więcej ciekawych funkcji do eksploracji: php.net/manual/en/class.splfileobject.php
Lukas Liesis
6
Dzięki. Tak, na przykład możesz dodać tę linię wcześniej, podczas gdy $ file-> setFlags (SplFileObject :: DROP_NEW_LINE); aby usunąć nowe linie na końcu linii.
elshnkhll,
O ile widzę, eof()w SplFileObject nie ma żadnej funkcji?
Chud37
3
Dzięki! Użyj również, rtrim($file->fgets())aby usunąć końcowe znaki nowej linii dla każdego ciągu linii, który jest czytany, jeśli nie chcesz.
Zamiast tego powinna to być zaakceptowana odpowiedź. Jest setki razy szybszy dzięki generatorom.
Tachi,
1
I jeszcze bardziej wydajna pamięć.
Nino Škopac
2
@ NinoŠkopac: Czy możesz wyjaśnić, dlaczego to rozwiązanie jest bardziej wydajne pod względem pamięci? Na przykład w porównaniu z SplFileObjectpodejściem.
k00ni
30
Użyj technik buforowania, aby odczytać plik.
$filename ="test.txt";
$source_file = fopen( $filename,"r")ordie("Couldn't open $filename");while(!feof($source_file)){
$buffer = fread($source_file,4096);// use a buffer of 4KB
$buffer = str_replace($old,$new,$buffer);///}
zasługuje na więcej miłości, ponieważ będzie działać z dużymi plikami, nawet tymi, które nie mają
znaków
Nie zdziwiłbym się, gdyby OP tak naprawdę nie dbał o rzeczywiste linie i chciał tylko np. Podać plik do pobrania. W takim przypadku odpowiedź jest w porządku (i co zrobi większość koderów PHP).
Álvaro González
30
Tam jest file() funkcja, która zwraca tablicę wierszy zawartych w pliku.
Plik o rozmiarze jednego GB zostałby wczytany do pamięci i przekonwertowany na tablicę zawierającą więcej niż jeden GB ... powodzenia.
FrancescoMM
4
To nie była odpowiedź na zadane pytanie, ale odpowiada na bardziej powszechne pytanie, które ma wiele osób, patrząc tutaj, więc nadal było przydatne, dzięki.
pilavdzice 26.04.16
2
file () jest bardzo wygodny do pracy z małymi plikami. Zwłaszcza, gdy chcesz tablicę () jako wynik końcowy.
funkcja
to zły pomysł, gdy większe pliki są odczytywane do tablicy jednocześnie
Flash Thunder
To źle psuje się na dużych plikach, więc dokładnie ta metoda nie działa.
Należy zauważyć, że ten kod zwróci tylko wiersze, dopóki nie pojawi się pierwszy pusty wiersz. Musisz przetestować na $ line! == false w trybie whilewhile (($line = stream_get_line($fp, 1024 * 1024, "\n")) !== false)
cebe
8
Uważaj na rzeczy „while (! Feof ... fgets ()”), fgets mogą otrzymać błąd (returnfing false) i zapętlić się na zawsze, nie osiągając końca pliku. kończy się pętla, sprawdź feof; jeśli nie jest prawdą, to wystąpił błąd.
Tak sobie radzę z bardzo dużym plikiem (testowanym do 100G). I jest szybszy niż fgets ()
$block =1024*1024;//1MB or counld be any higher than HDD block_size*2if($fh = fopen("file.txt","r")){
$left='';while(!feof($fh)){// read the file
$temp = fread($fh, $block);
$fgetslines = explode("\n",$temp);
$fgetslines[0]=$left.$fgetslines[0];if(!feof($fh))$left = array_pop($lines);foreach($fgetslines as $k => $line){//do smth with $line}}}
fclose($fh);
function read_file($filename =''){
$buffer = array();
$source_file = fopen( $filename,"r")ordie("Couldn't open $filename");while(!feof($source_file)){
$buffer[]= fread($source_file,4096);// use a buffer of 4KB}return $buffer;}
Stworzyłoby to jedną tablicę więcej niż jednego GB w pamięci (powodzenia) podzieloną nawet nie w wierszach, ale na dowolne fragmenty 4096 znaków. Dlaczego, u licha, chcesz to zrobić?
fgets()
bez$length
parametru.Odpowiedzi:
Możesz użyć tej
fgets()
funkcji do odczytania pliku linia po linii:źródło
too large to open in memory
części?źródło
if($file)
przed pętlą whilefeof()
już nie istnieje?Możesz użyć obiektowej klasy interfejsu dla pliku - SplFileObject http://php.net/manual/en/splfileobject.fgets.php (PHP 5> = 5.1.0)
źródło
eof()
w SplFileObject nie ma żadnej funkcji?rtrim($file->fgets())
aby usunąć końcowe znaki nowej linii dla każdego ciągu linii, który jest czytany, jeśli nie chcesz.Jeśli otwierasz duży plik, prawdopodobnie chcesz użyć Generatorów obok fgets (), aby uniknąć ładowania całego pliku do pamięci:
Użyj tego w ten sposób:
W ten sposób możesz przetwarzać pojedyncze linie plików w foreach ().
Uwaga: Generatory wymagają> = PHP 5.5
źródło
SplFileObject
podejściem.Użyj technik buforowania, aby odczytać plik.
źródło
Tam jest
file()
funkcja, która zwraca tablicę wierszy zawartych w pliku.źródło
źródło
file()
.Nie było oczywistej odpowiedzi we wszystkich odpowiedziach.
PHP ma schludny parser ograniczników strumieniowych dostępny specjalnie do tego celu.
źródło
while (($line = stream_get_line($fp, 1024 * 1024, "\n")) !== false)
Uważaj na rzeczy „while (! Feof ... fgets ()”), fgets mogą otrzymać błąd (returnfing false) i zapętlić się na zawsze, nie osiągając końca pliku. kończy się pętla, sprawdź feof; jeśli nie jest prawdą, to wystąpił błąd.
źródło
Tak sobie radzę z bardzo dużym plikiem (testowanym do 100G). I jest szybszy niż fgets ()
źródło
Jednym z popularnych rozwiązań tego pytania będą problemy z nowym charakterem linii. Można to łatwo naprawić za pomocą prostego
str_replace
.źródło
SplFileObject jest użyteczny, jeśli chodzi o obsługę dużych plików.
źródło
źródło
Funkcja do odczytu ze znakiem powrotu tablicy
źródło