从二进制文件中删除

时间:2014-04-27 20:03:25

标签: c

我试图通过用'标记它来从二进制文件中删除一个Employee。 *'在Employee.Firstname的第一个字节,但是如果该文件上有多个员工,我尝试删除第二个员工,并将其标记为删除' *'它只会标记第一个Employee.Firstname的第一个字节,其中包含' *'。

以下是我写文件的方式:

struct EmployeeInformation{

        char Firstname[32];
        char Lastname[32];
        char Address[32];
        char ID[8];
        char Duration[8];
    }

struct EmployeeInformation Employee;

void AddEmployee()
{
    FILE *fd;

    printf("\n\n>>Add Employee<<\n");

    //I use fgets and get all Employee info I just didn't include it for reading purposes.

    if((fd = fopen(BINARY_FILE, "ab+")) == NULL)
    {
        printf("Error in opening file.\n\n");
        getchar();
    }


    else
    {
        //Write Employee to file.
        fwrite(&Employee, sizeof(Employee), 1, fd);

        printf("\nEmployee Added!\n\n");
    }
    fclose(fd);


}

以下是删除员工的代码。

void DeleteEmployee()
{
    FILE *fd;
    char EmployeeID[8];
    long Pos = 0;
    fpos_t pos;

    printf("\n>>Delete Employee<<\n");

    //Ask user for ID of employee they wish to delete.
    printf("Employee ID:");
    fgets(EmployeeID, 6, stdin);

    if ((fd = fopen(BINARY_FILE, "rb+")) == NULL)
    {

        printf("Error, Cannot Open File.\n");
    }
    else
    {

        while(fread(&Employee, sizeof(struct EmployeeInformation), 1, fd) != 0)
        {

            if(strcmp(EmployeeID, Employee.ID) == 0)
            {
                    //Employee Found
                    printf("Employee Found!\n");

                    //Get Current Position in file.
                    Pos = fgetpos(fd, &pos);

                    //Go to that Postion.
                    fseek(fd, Pos, SEEK_SET);
                    //Mark for deletion with '*'
                    fputc('*', fd);

                    printf("Firstname: %s\n",Employee.Firstname);
            }
            else
            {
                printf("Employe Not Found!\n\n");
            }
        }
    }
    fclose(fd);

}

3 个答案:

答案 0 :(得分:2)

您刚从fgetpos获得的位置> 您刚刚阅读的记录。您需要在执行阅读前致电fgetpos或在致电sizeof(struct EmployeeInformation)之前从该职位中减去fseek。当你向后搜索然后写一个字节时,你也会弄乱当前的位置。最后,fgetpos并没有回复你的想法;将其替换为ftell

我会建议:

long int pos = ftell(fd);
while(fread(&Employee, sizeof(struct EmployeeInformation), 1, fd) != 0)
{
    if(strcmp(EmployeeID, Employee.ID) == 0)
    {
            //Employee Found
            printf("Employee Found!\n");

            //Go to the BEGINNING of the record
            fseek(fd, pos, SEEK_SET);
            //Mark for deletion with '*'
            fputc('*', fd);

            printf("Firstname: %s\n",Employee.Firstname);

            //Now position back to the end of the record (-1 because we advanced 1
            //byte when we did fputc() above
            fseek(pd, pos+sizeof(struct EmployeeInformation)-1, SEEK_SET);
    }
    else
    {
        printf("Employe Not Found!\n\n");
    }

    //We should now be at the beginning of the next record - mark the position
    pos = ftell(fd);
}

答案 1 :(得分:0)

而不是:

fseek(fd, Pos, SEEK_SET);

DO

fsetpos(f, &pos);

......或类似的东西,很可能你必须减去sizeof(Employee)

确保您寻找正确的位置,来自正确的变量,并包含正确的值。

如果您的文件不是太长,请使用ftellfseek进行定位。否则,请使用fgetposfsetpos。永远不要混合这些。

答案 2 :(得分:0)

既然你正在阅读每个单独的记录,直到找到你要找的那个记录,你可以有一个计数器来计算读取的记录数,然后当你找到你要删除的记录时就行了

fseek( fp, (current-1)*sizeof(Employee), SEEK_SET); 
fputc( '*', fp );

然后

fseek(fp, current*sizeof(Employee), SEEK_SET); 

定位于下一个结构,因为写'*'将移动fp。