3

私は PHP には問題ありませんが、おそらくここにいる皆さんの半分ほどではありません。

私は基本的に、巨大なテキストファイルから行を取得する方法を見つけようとしています....それは基本的に、行番号で呼び出したいキーワードのリストですが、できればそれに到達する前にそれらすべてを通過することはありません行.....そうしないと、サーバーが明らかにクラッシュする可能性があります。

現時点ではこれを使用しています

$lines = file('http://www.mysite.com/keywords.txt');
foreach ($lines as $line_num => $line) {
   echo "$line_num";
}

これは機能しますが、これはファイル全体をメモリに入れているため、使用量を節約するためのより良い方法が必要であると確信しています。単純にphpに行番号97を与えると言うことができれば、うーんルール....

皆さんが私よりずっと賢いので、解決策を思いつくことができることを願っています:P ty

4

3 に答える 3

2

SplFileObject を使用する

 $file = "test.txt";
  $line_number = 1000;
  $file_obj = new SplFileObject( $file );
    /*** seek to the line number ***/
  $file_obj->seek( $line_number );

   /*** return the current line ***/
   echo  $file_obj->current();
于 2013-02-18T11:16:58.463 に答える
2

行が単なるテキストで長さが可変の場合、どの行が #97 であるかを知ることはできません。97 番目になるのは、前に 96 行あることだけです。

そのため、その時点までのファイル全体を読み取る必要があります (これが SplFileObject の機能です)。

$fp = fopen("keywords.txt", "r");
while($line--)
{
    if (feof($fp))
        // ERROR: line does not exist
    $text = fgets($fp, 1024); // 1024 = max length of one line
}
fclose($fp);

しかし、各行の前に行番号を保存できる場合、つまりファイルは

...
95 abbagnale
96 abbatangelo
97 abbatantuono
98 ...

次に、一種の二分探索を実装できます。

- start with s1 = 0 and s2 = file length
- read a keyword and line number at seek position s3 = (s1+s2)/2 (*)
- if line number is less than desired, s1 = s3; else s2 = s3; and repeat previous step.
- if line number is the one desired, strip the number from the text and you get the keyword.

(*) 行は正確に s# で開始されない可能性が高いため、 2 つのfgetsが必要です。「近い」場合は、より大きなチャンクを読み取って行に分割する方が高速になります。たとえば、170135 行をシークして 170180 行を読み込むとします。シーク位置を 1 キロバイト巻き戻し、1 キロバイトのデータを読み込み、そこで 170135 をシークします。

または、さまざまな行の長さがあまり変わらない場合は、固定サイズの行を保存する価値があります (ここで、「#」は実際にはスペースである必要があり、行の長さでは、行末記号をカウントする必要があります \nまたは \r\n):

abbagnale#########
abbatangelo#######
abbatantuono######

次に、各キーワードが 32 バイトであるとします。

$fp = fopen("keywords.txt", "r");
fseek($fp, 97 * 32, SEEK_SET);
$text = trim(fgets($fp, 32));
fclose($fp);

多かれ少なかれ瞬時になります。

ただし、ファイルがリモート サーバー上にある場合でも、ファイル全体 (目的の行まで) をダウンロードする必要があります。検索を実行できるリモート サーバー上に「スキャナー」スクリプトを配置することで、より適切なサービスを提供できます。その後、実行できます

$text = file_get_contents("http://www.mysite.com/keywords.php?line=97");

ミリ秒単位でラインを取得します。

于 2013-02-18T11:23:35.800 に答える
0

ほとんどすべての言語で、最初に何らかの方法で読み取ることなく、ファイルから「行番号 x」を取得する方法はありません。結局のところ、行は 2 つの行末文字の間にあるものにすぎません。ファイルから '文字番号 x' を取得することは、ファイル全体をロードしなくても実行できますが (多少困難があります)、'行番号 x' を取得するには、x までのすべての行をロードしないと実行できません (そして、ほとんどの方法では、すべての行をロードする必要があります)

行 x までのすべての行をロードする方法は次のとおりです ( fgetsを使用)。

$f = fopen('http://www.mysite.com/keywords.txt');
$i=97
$text=""
while (($text = fgets($f,2048)) !== false && $i>0) {
       $i--
}
echo $text
于 2013-02-18T11:24:13.827 に答える