Je veux lire un fichier ligne par ligne, mais sans le charger complètement en mémoire.
Mon fichier est trop volumineux pour pouvoir être ouvert en mémoire. Si j'essaie de le faire, les erreurs de mémoire sont toujours insuffisantes.
La taille du fichier est de 1 Go.
Vous pouvez utiliser la fonction fgets()
pour lire le fichier ligne par ligne:
$handle = fopen("inputfile.txt", "r");
if ($handle) {
while (($line = fgets($handle)) !== false) {
// process the line read.
}
fclose($handle);
} else {
// error opening the file.
}
if ($file = fopen("file.txt", "r")) {
while(!feof($file)) {
$line = fgets($file);
# do same stuff with the $line
}
fclose($file);
}
Vous pouvez utiliser une classe d'interface orientée objet pour un fichier - SplFileObject http://php.net/manual/en/splfileobject.fgets .php (PHP 5> = 5.1.0)
<?php
$file = new SplFileObject("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;
Si vous ouvrez un gros fichier, vous voudrez probablement utiliser Generators avec fgets () pour éviter de charger tout le fichier en mémoire:
/**
* @return Generator
*/
$fileData = function() {
$file = fopen(__DIR__ . '/file.txt', 'r');
if (!$file)
die('file does not exist or cannot be opened');
while (($line = fgets($file)) !== false) {
yield $line;
}
fclose($file);
};
Utilisez-le comme ceci:
foreach ($fileData() as $line) {
// $line contains current line
}
De cette façon, vous pouvez traiter des lignes de fichier individuelles dans foreach ().
Remarque: Les générateurs nécessitent> = PHP 5.5
Utilisez des techniques de mise en mémoire tampon pour lire le fichier.
$filename = "test.txt";
$source_file = fopen( $filename, "r" ) or die("Couldn't open $filename");
while (!feof($source_file)) {
$buffer = fread($source_file, 4096); // use a buffer of 4KB
$buffer = str_replace($old,$new,$buffer);
///
}
Il existe une fonction file()
qui renvoie un tableau des lignes contenues dans le fichier.
foreach(file('myfile.txt') as $line) {
echo $line. "\n";
}
foreach (new SplFileObject(__FILE__) as $line) {
echo $line;
}
Soyez prudent avec les éléments "while (! Feof ... fgets ()", fgets peut obtenir une erreur (returnfing false) et boucle en boucle sans atteindre la fin du fichier. Codaddict était proche de l'exactitude, mais lorsque votre "tant que fgets" boucle se termine, vérifiez feof; sinon, vous avez une erreur.
La réponse évidente ne figurait pas dans toutes les réponses. PHP dispose d'un analyseur de séparateur de flux en continu parfaitement conçu à cet effet.
$fp=fopen("/path/to/the/file", "r+");
while ($line = stream_get_line($fp, 1024 * 1024, "\n"))
{
echo $line;
}
fclose($fp);
Une des solutions populaires à cette question aura des problèmes avec le caractère de nouvelle ligne. Il peut être corrigé assez facilement avec un simple str_replace
.
$handle = fopen("some_file.txt", "r");
if ($handle) {
while (($line = fgets($handle)) !== false) {
$line = str_replace("\n", "", $line);
}
fclose($handle);
}
C'est comme ça que je gère avec de très gros fichiers (testé avec jusqu'à 100G). Et c'est plus rapide que fgets ()
$block =1024*1024;//1MB or counld be any higher than HDD block_size*2
if ($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);
SplFileObject est utile pour gérer des fichiers volumineux.
function parse_file($filename)
{
try {
$file = new SplFileObject($filename);
} catch (LogicException $exception) {
die('SplFileObject : '.$exception->getMessage());
}
while ($file->valid()) {
$line = $file->fgets();
//do something with $line
}
//don't forget to free the file handle.
$file = null;
}
<?php
echo '<meta charset="utf-8">';
$k= 1;
$f= 1;
$fp = fopen("texttranslate.txt", "r");
while(!feof($fp)) {
$contents = '';
for($i=1;$i<=1500;$i++){
echo $k.' -- '. fgets($fp) .'<br>';$k++;
$contents .= fgets($fp);
}
echo '<hr>';
file_put_contents('Split/new_file_'.$f.'.txt', $contents);$f++;
}
?>