11

Cを使用して、コンテンツ全体をループせずにファイルの最後の行のみを読み取る方法はありますか?

ファイルには何百万もの行が含まれており、それぞれが整数(long long int)を保持しています。ファイル自体は非常に大きくなる可能性があり、最大で 1000 MB になると思います。最後の行が 55 桁を超えないことは確かですが、2 桁のみになる可能性もあります。あらゆる種類のデータベースを使用するという選択肢はありません...私はすでにそれを検討しました。

ばかげた質問かもしれませんが、PHP のバックグラウンドがあるため、答えるのが難しいと思います。私はいたるところを見ましたが、きれいなものは何も見つかりませんでした。

現在私は使用しています:

if ((fd = fopen(filename, "r")) != NULL) // open file
{
    fseek(fd, 0, SEEK_SET); // make sure start from 0
    while(!feof(fd))
    {
        memset(buff, 0x00, buff_len); // clean buffer
        fscanf(fd, "%[^\n]\n", buff); // read file *prefer using fscanf
    }
    printf("Last Line :: %d\n", atoi(buff)); // for testing I'm using small integers
}

このようにして、ファイルのコンテンツをループし、ファイルが最大 50 万行を超えるとすぐに処理が遅くなります....

前もって感謝します。マキシム

4

4 に答える 4

7

fseekfileSize - 55て先読みするだけですか?

于 2012-12-09T19:02:34.000 に答える
5

行の最大長がある場合は、末尾までの距離までシークします。最後まで読み、バッファ内の最後の行末を見つけます。

行の最大長がない場合は、適切な値を推測し、最後にその長さを読み取ります。行末がない場合は、推測を 2 倍にして、もう一度試してください。

あなたの場合:

/* max length including newline */
static const long max_len = 55 + 1;
/* space for all of that plus a nul terminator */
char buf[max_len + 1];

/* now read that many bytes from the end of the file */
fseek(fd, -max_len, SEEK_END);
ssize_t len = read(fd, buf, max_len);

/* don't forget the nul terminator */
buf[len] = '\0';

/* and find the last newline character (there must be one, right?) */
char *last_newline = strrchr(buf, '\n');
char *last_line = last_newline+1;
于 2012-12-09T19:03:47.023 に答える
3

で開き、"rb"バイナリを読み取っていることを確認します。次にfseek(..., SEEK_END)、最初の行セパレーターが見つかるまで、後ろからバイトの読み取りを開始します (行の最大長が 55 文字であることがわかっている場合は、55 文字を読み取ります...)。

于 2012-12-09T19:03:09.523 に答える
2

わかった。それはすべて私のために働いた。私は何か新しいことを学びました。サイズが 41 MB で 500k 行を超えるファイルの最後の行が即座に読み取られました。皆さん、特に「役に立たない」に感謝します (あなたのニックネームの論争が大好きです)。将来誰かが恩恵を受けることができることを願って、ここにコードを投稿します。

ファイルの最後の行のみを読み取る:

ファイルは、新しい行が追加されるように構成されており、私の場合、どの行も 55 文字より短いと確信しています。

file contents:
------------------------
2943728727
3129123555
3743778
412912777
43127787727
472977827

------------------------

新しい行が追加されていることに注意してください。

FILE *fd;                           // File pointer
char filename[] = "file.dat";       // file to read
static const long max_len = 55+ 1;  // define the max length of the line to read
char buff[max_len + 1];             // define the buffer and allocate the length

if ((fd = fopen(filename, "rb")) != NULL)  {      // open file. I omit error checks

    fseek(fd, -max_len, SEEK_END);            // set pointer to the end of file minus the length you need. Presumably there can be more than one new line caracter
    fread(buff, max_len-1, 1, fd);            // read the contents of the file starting from where fseek() positioned us
    fclose(fd);                               // close the file

    buff[max_len-1] = '\0';                   // close the string
    char *last_newline = strrchr(buff, '\n'); // find last occurrence of newlinw 
    char *last_line = last_newline+1;         // jump to it

    printf("captured: [%s]\n", last_line);    // captured: [472977827]
}

乾杯!マキシム

于 2012-12-09T22:11:00.660 に答える