2009-06-30 7 views

答えて

37

最も単純素朴な解決策は単純です:

$file = "/path/to/file"; 
$data = file($file); 
$line = $data[count($data)-1]; 

けれども、これはメモリにファイル全体をロードします。おそらく問題(またはそうではない)。

$file = escapeshellarg($file); // for the security concious (should be everyone!) 
$line = `tail -n 1 $file`; 
+0

spot on、ありがとうMatthew – waxical

+0

FYI、私はtailを使用しました... – waxical

+1

escapeshellarg()を使用しない限り、これは非常に危険です。http://de.php.net/manual/en/function.escapeshellarg.php – soulmerge

2

ファイルを1行ずつ読み込み、最後に読み込んだ行を保存する必要があります。

またはUNIX/Linuxの場合は、それはあなたが探しているものであるようにこれが見えます

tail -n 1 filename 
13

シェルコマンドの尾を使用して検討するかもしれない:

tekkie.flashbit.net: Tail functionality in PHP

それは、その機能を実現負のインデックスを持つfseek()を使用して、最後からファイルをロールアップします。返される線の数を定義することができます。

コードも利用可能as a Gist on GitHubです:

// full path to text file 
define("TEXT_FILE", "/home/www/default-error.log"); 
// number of lines to read from the end of file 
define("LINES_COUNT", 10); 


function read_file($file, $lines) { 
    //global $fsize; 
    $handle = fopen($file, "r"); 
    $linecounter = $lines; 
    $pos = -2; 
    $beginning = false; 
    $text = array(); 
    while ($linecounter > 0) { 
     $t = " "; 
     while ($t != "\n") { 
      if(fseek($handle, $pos, SEEK_END) == -1) { 
       $beginning = true; 
       break; 
      } 
      $t = fgetc($handle); 
      $pos --; 
     } 
     $linecounter --; 
     if ($beginning) { 
      rewind($handle); 
     } 
     $text[$lines-$linecounter-1] = fgets($handle); 
     if ($beginning) break; 
    } 
    fclose ($handle); 
    return array_reverse($text); 
} 

$fsize = round(filesize(TEXT_FILE)/1024/1024,2); 

echo "<strong>".TEXT_FILE."</strong>\n\n"; 
echo "File size is {$fsize} megabytes\n\n"; 
echo "Last ".LINES_COUNT." lines of the file:\n\n"; 

$lines = read_file(TEXT_FILE, LINES_COUNT); 
foreach ($lines as $line) { 
    echo $line; 
} 
+0

興味深いですが、非常に簡単な方法の次には全く問題がありません(実際には非常に重労働のサーバーにいない限り) –

+6

「まったく役に立たない」は少し厳しいです – Tomalak

+0

少しでも...誰かが「尾」を使用するのが実際にはボトルネックを引き起こしていて、大規模なデータベースの操作ではないことを証明できない限り、私はそれを使用することを嫌に思っています。 –

0

あなたはfile機能は、ラインによって、ファイル、行の内容を読み取り、の要素として各行を返す行毎にファイルを読みたい場合はアレイ。

だからあなたのような単純なもの行うことができます:

$lines = file('log.txt'); 
$lastLine = array_pop($lines); 
+3

本当ですか? 99.99%が私に関心がない複数のメガバイトのログファイルに対しては、すぐに捨てるために、すべてのファイルを配列にロードしないようにします。 – Tomalak

+0

これは非効率的であることを否定しませんが、機能します。ファイルの長さは誰が知っていますか?自分の環境でtailコマンドを使用しますが、WiseDonkeyは何も指定していませんでした。あなたがリンクした素晴らしい機能です。 –

+1

file()とfile_get_contents()はどちらも優れたファイル操作関数です。ファイルが比較的小さく、何かをすばやく簡単に実行したいと思っている場合に特に役に立ちます。 –

7
define('YOUR_EOL', "\n"); 
$fp = fopen('yourfile.txt', 'r'); 

$pos = -1; $line = ''; $c = ''; 
do { 
    $line = $c . $line; 
    fseek($fp, $pos--, SEEK_END); 
    $c = fgetc($fp); 
} while ($c != YOUR_EOL); 

echo $line; 

fclose($fp); 

それがメモリに完全なファイルをロードしませんので、あなたが同じを使用する場合、これは、...、あなたの正しい行末に

設定YOUR_EOL優れている:より良い解決策はこれですスクリプトが存在するOSのデフォルトの行末として行末を使用する場合は、定数PHP_EOLを使用できます。

1

このファイルは、1行または0行のファイルに対して改行されません。

function readlastline($fileName) 
{ 

     $fp = @fopen($fileName, "r"); 
     $begining = fseek($fp, 0);  
     $pos = -1; 
     $t = " "; 
     while ($t != "\n") { 
      fseek($fp, $pos, SEEK_END); 
      if(ftell($fp) == $begining){ 
       break; 
      } 
      $t = fgetc($fp); 
      $pos = $pos - 1; 
     } 
     $t = fgets($fp); 
     fclose($fp); 
     return $t; 
} 
4
function seekLastLine($f) { 
    $pos = -2; 
    do { 
     fseek($f, $pos--, SEEK_END); 
     $ch = fgetc($f); 
    } while ($ch != "\n"); 
} 

-2最後の文字は\n

1

ことができるので...理由だけで、最後の行を読んで?

function readLines($fp, $num) { 

    $line_count = 0; $line = ''; $pos = -1; $lines = array(); $c = ''; 

    while($line_count < $num) { 
     $line = $c . $line; 
     fseek($fp, $pos--, SEEK_END); 
     $c = fgetc($fp); 
     if($c == "\n") { $line_count++; $lines[] = $line; $line = ''; $c = ''; } 
    } 
    return $lines; 
} 

$filename = "content.txt"; 
$fp = @fopen($filename, "r"); 

print_r(readLines($fp, 2)); 

fclose($fp); 
+2

これはOPが必要とするものなのですか? lol – dtbarne

0

@unique_stephen、あなたの答えには欠陥があります。 PHP fseekは、成功すれば0を返し、失敗した場合は-1を返します。結果を$ begin(sic)に格納し、後でそれをftell()のフィルタで使用することは正しくありません。私の評判が高いなら私はあなたに投票してコメントを残したでしょう。これはunique_stephenの関数の修正版です。

function readlastline($fileName) 
{ 
    $fp = @fopen($fileName, "r"); 
    if (fseek($fp, 0) == -1) 
     exit('Cannot seek to beginning of the file'); 
    $pos = -1; 
    $t = " "; 
    while ($t != "\n") { 
     if (fseek($fp, $pos, SEEK_END) == -1) 
      exit('Cannot seek to the end of the file'); 
     if (ftell($fp) == 0) { 
      break; 
     } 
     $t = fgetc($fp); 
     $pos = $pos - 1; 
    } 
    $t = fgets($fp); 
    fclose($fp); 
    return $t; 
} 

注:PHPのfseek関数は、32ビットは64ビットのバイナリにも、署名されているPHP_MAX_INTを超えるファイルの末尾に求めることを管理することはできません。

+1

これは質問に対する答えを提供しません。十分な[評判](https://stackoverflow.com/help/whats-reputation)があれば、[投稿にコメントする]ことができます(https://stackoverflow.com/help/privileges/comment)。代わりに、[質問者からの明確化を必要としない回答を提供する](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-c​​an- i-do-代わりに)。 - [レビューから](/レビュー/低品質の投稿/ 18923154) –

+0

はい、質問に対する回答は既にあります。答えにコメントを残すことができないという問題は、答えをコメントとして残しておきたくない場合は、解決する必要があることです。 @ unique_stephenの応答の正しいバージョンを与えるために答えを編集します。 – Earnie

関連する問題