C语言读取文件最后一行

Reading last line of a file In C

我正在思考如何读取文件最后一行的逻辑,但我想不出答案。 ACCOUNTNUM 信息是一个结构。 my .dat file who has 3 acc numbers already。在这里我想知道如何获取最后一个帐户 number/line 即 2022-3.

这是函数

LastAccountNumber(){
    ACCOUNTNUM info;
    file = fopen("acctNumbers.dat","r");
    char firstAcc[50]="2022-1";//ignore this I was gonna compare this with the last line.
    
    while((fread(&info,sizeof(struct accountNum),1,file))==1){
            printf("\nAcc No %s",info.sAccountNum);
    }
        
    }
    
}

这是我的结构

struct accountNum{
    int sequence;
    char sAccountNum[16];
};
typedef struct accountNum ACCOUNTNUM;

我的 acctNumbers.dat 文件的内容。

2022-1       ú·   2022-2       ú·   2022-3       ú·

你是一条条读取记录存入info,按理说循环结束时存入info的元素ACCOUNTNUM正好是最后一条记录在文件中,将以下代码稍作修改,以说明这一点:

#include <stdio.h>

struct accountNum {
    int sequence;
    char sAccountNum[16];
};
typedef struct accountNum ACCOUNTNUM;
int LastAccountNumber(ACCOUNTNUM* info) {

    int success = 0;
    FILE* file = fopen("acctNumbers.dat", "rb");
    if (file == NULL) {
        return -1;  // Allows you to document different types of errors
    }
    while ((fread(info, sizeof(struct accountNum), 1, file)) == 1) {
        success = 1;
    }
    fclose(file);
    return success;
}

int main() {
    ACCOUNTNUM N[] = {{123, "2022-1"}, {111, "2022-2"}, {321, "2022-3"}};
    FILE* file = fopen("acctNumbers.dat", "wb");

    fwrite(N, 1, sizeof N, file);
    fclose(file);

    ACCOUNTNUM info;

    if (LastAccountNumber(&info) == 1) //if -1 couldn't open file, 0 no record read
        printf("\nAcc No %s", info.sAccountNum);
}

将输出:

Acc No 2022-3

这正是文件中的最后一个元素。

实时样本:https://onlinegdb.com/q760Ow1vQc

请注意,您应该验证 fopen 的 return 值以确认对文件的正确访问。还建议在完成后关闭文件。

您可以循环调用 fread 直到它 returns 0,然后打印读取的最后一条记录:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct accountNum
{
    int sequence;
    char sAccountNum[16];

} ACCOUNTNUM;

int main( void )
{
    FILE *fp;
    ACCOUNTNUM info;
    bool success = false;

    //open file and verify that it is open
    fp = fopen( "acctNumbers.dat", "r" );
    if ( fp == NULL )
    {
        fprintf( stderr, "Error opening file!\n" );
        exit( EXIT_FAILURE );
    }

    //skip to last record
    while( ( fread( &info, sizeof info, 1, fp) ) == 1 )
    {
        //set variable to indicate that we have found at
        //least one record
        success = true;
    }

    //print last record, if it exists
    if ( success )
        printf( "Acc No: %s\n", info.sAccountNum );
    else
        printf( "No records found.\n" );

    //cleanup
    fclose( fp );
}

但是,只有当您确定最后一个 fread 不会执行部分读取时,这才能保证有效,即如果您确定文件大小是 [=16= 的精确倍数].因为如果 fread 确实执行了部分读取,那么缓冲区内容将是不确定的。

如果不能排除部分读取的可能,那么可以使用两个buffer读取,交替使用:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct accountNum
{
    int sequence;
    char sAccountNum[16];

} ACCOUNTNUM;

int main( void )
{
    FILE *fp;
    ACCOUNTNUM info[2];
    int current_index = 0;
    bool success = false;
    size_t ret;

    //open file and verify that it is open
    fp = fopen( "acctNumbers.dat", "r" );
    if ( fp == NULL )
    {
        fprintf( stderr, "Error opening file!\n" );
        exit( EXIT_FAILURE );
    }

    for (;;) //infinite loop, equivalent to while(1)
    {
        //read record from file
        ret = fread( &info[current_index], sizeof *info, 1, fp);

        //swap buffer index
        current_index = current_index == 0 ? 1 : 0;

        //restart loop if successful
        if ( ret == 1 )
        {
            //set variable to indicate that we have found at
            //least one record
            success = true;

            continue;
        }

        //break out of loop
        break;
    }

    //print last record, if it exists
    if ( success )
        printf( "Acc No: %s\n", info[current_index].sAccountNum );
    else
        printf( "No records found.\n" );

    //cleanup
    fclose( fp );
}

或者您可以使用单个缓冲区并通过交换函数的第二个和第三个参数来更改调用函数的方式 fread,这样您就可以检测是否发生了部分读取。如果确实发生,您可以打印一条错误消息并终止程序。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct accountNum
{
    int sequence;
    char sAccountNum[16];

} ACCOUNTNUM;

int main( void )
{
    FILE *fp;
    ACCOUNTNUM info;
    bool success = false;
    size_t ret;

    //open file and verify that it is open
    fp = fopen( "acctNumbers.dat", "r" );
    if ( fp == NULL )
    {
        fprintf( stderr, "Error opening file!\n" );
        exit( EXIT_FAILURE );
    }

    //read one record per loop iteration
    while ( ( ret = fread( &info, 1, sizeof info, fp) ) != 0 )
    {
        //verify that no partial read occurred
        if ( ret != sizeof info )
        {
            fprintf( stderr, "Error: Partial read detected!\n" );
            exit( EXIT_FAILURE );
        }

        //set variable to indicate that we have found at
        //least one record
        success = true;
    }

    //print last record, if it exists
    if ( success )
        printf( "Acc No: %s\n", info.sAccountNum );
    else
        printf( "No records found.\n" );

    //cleanup
    fclose( fp );
}