C:只读取文件的最后一行。没有循环

时间:2012-12-09 19:00:47

标签: c file-io

使用C,有没有办法只读取 文件的最后一行 而不循环它的整个内容?

事情是该文件包含数百万的行,每行包含一个整数(long long int)。文件本身可能非常大,我认为甚至高达1000mb。我确定最后一行不会超过55位数,但也可能只有2位数。使用任何类型的数据库都没有选择...我已经考虑过了。

也许这是一个愚蠢的问题,但是来自PHP背景我觉得很难回答。我到处看,但没有发现 clean

目前我正在使用:

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
}

这样我循环文件的内容,一旦文件大于~500k行,事情就会慢下来......

提前谢谢你。 格言

4 个答案:

答案 0 :(得分:6)

只需fseekfileSize - 55并向前阅读?

答案 1 :(得分:5)

如果有最大行长度,请在结束之前寻找距离。 读到最后,找到缓冲区中的最后一行。

如果没有最大行长度,请猜出一个合理的值,最后读取那么多,如果没有行结束,请加倍猜测并重试。

在你的情况下:

/* 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;

答案 2 :(得分:3)

使用"rb"打开以确保您正在阅读二进制文件。然后fseek(..., SEEK_END)并开始从后面读取字节,直到找到第一行分隔符(如果你知道最大行长度是55个字符,读取55个字符......)。

答案 3 :(得分:1)

确定。这一切对我有用。我学到了新东西。文件41mb大的最后一行和> 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]
}

喝彩! 格言