更新包含c中结构的二进制文件,更改为损坏文件的其余部分的偏移量

我正在尝试编写一个方法,在给定包含要更新或追加的值的文件的情况下,将更新第二个二进制文件。

显然,当我覆盖二进制文件中的结构时,偏移量会以某种方式发生变化,从而破坏其后的所有内容。 我做错了什么,有没有办法在不截断和附加到文件的情况下阻止这种情况?

当前代码:

typedef struct{ int number; double price; } stock; void update(char* updatefile, char* binfile){ FILE *fin, *fout; stock *currStock; stock *updateStock; int currPos; int update; int val1=0; double val2=0; currStock = malloc(sizeof(stock)); updateStock = malloc(sizeof(stock)); fin=fopen(updatefile,"r"); while (fscanf(fin, " \n%d %lf",&val1,&val2) != EOF) { currStock->number = val1; currStock->price = val2; printf("Updating file with stock: %d,%1.2lf\n",currStock->number,currStock->price); fout = fopen(binfile,"r+b"); update = 0; while(fread((void*)updateStock,sizeof(stock),1,fout)==1&&!update){ printf("position: %ld\n",ftell(fout)); printf("update stock: %d, %1.2lf\n",updateStock->number,updateStock->price); if(updateStock->number==currStock->number){ //&&updateStock->price!=currStock->price printf("updating stock with new price: %1.2lf\n",currStock->price); currPos = ftell(fout); printf("ftell = %d\n",currPos); fseek(fout,currPos-sizeof(stock),SEEK_SET); printf("ftell after seek: %ld\n",ftell(fout)); fwrite(currStock,sizeof(stock),1,fout); //fseek(fout,sizeof(stock),SEEK_CUR); update = 1; } } if(!update){ fseek(fout,0,SEEK_END); fwrite(currStock,sizeof(stock),1,fout); } if(fclose(fout)){ printf("value updated\n"); } } if(!feof(fin)){ printf("Error reading from file. Please check file format\n"); exit(0); } if(fclose(fin)){ puts("Error closing update file"); } printf("File updated.\n"); free(currStock); free(updateStock); return; } 

输出:(使用另一种方法显示二进制文件内容)

 stock in file: 1, 2.50 stock in file: 2, 5.43 stock in file: 3, 12.32 stock in file: 4, 0.54 stock in file: 5, 7.23 Updating file with stock: 2,3.40 position: 16 update stock: 1, 2.50 position: 32 update stock: 2, 5.43 updating stock with new price: 3.40 ftell = 32 ftell after seek: 16 Updating file with stock: 4,6.50 position: 16 update stock: 1, 2.50 position: 32 update stock: 2, 3.40 position: 48 update stock: 2, 5.43 position: 64 update stock: 1088, -41614952599525078000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00 position: 80 update stock: 1343, 0.00 Updating file with stock: 7,6.12 position: 18 update stock: 1, 2.50 position: 34 update stock: 2, 3.40 position: 50 update stock: 2, 5.43 position: 66 update stock: 1088, -41614952599525078000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00 position: 82 update stock: 1343, 0.00 File updated. stock in file: 1, 2.50 stock in file: 2, 3.40 stock in file: 2, 5.43 stock in file: 1088, -41614952599525078000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00 stock in file: 1343, 0.00 

编辑:我知道这不是更新文件的最有效方法(打开每个更新的结束),但我想弄清楚为什么在修复算法之前它会破坏它。

edit2:使用截断和追加工作,但我仍然想知道为什么这不起作用。

看起来问题正在发生,因为您在使用模式r +打开的文件写入后直接执行读取。 “C in a Nutshell”一书指出:

如果模式字符串包含加号,则模式允许输入和输出,并且必须在读取和写入文件之间同步文件位置指示符。 通过调用fflush()或文件定位函数 – fseek(),fsetpos()或rewind() – 在写入之后和读取之前,以及在读取之后和写入之前调用文件定位函数来执行此操作(除非它确定你已经阅读到文件的末尾)。

问题出在你的嵌套最多while()循环中:

 /*** Read occurs here... ***/ while(fread((void*)updateStock,sizeof(stock),1,fout)==1&&!update){ printf("position: %ld\n",ftell(fout)); printf("update stock: %d, %1.2lf\n",updateStock->number,updateStock->price); if(updateStock->number==currStock->number){ printf("updating stock with new price: %1.2lf\n",currStock->price); currPos = ftell(fout); printf("ftell = %d\n",currPos); fseek(fout,currPos-sizeof(stock),SEEK_SET); printf("ftell after seek: %ld\n",ftell(fout)); /** Write occurs here but... during the next while() check a read is immediately performed. **/ fwrite(currStock,sizeof(stock),1,fout); update = 1; } 

我在你的fwrite()之后立即添加了以下内容,它似乎正在工作……

 fflush(fout); 

另外,只是旁注。 你的currPos是一个int而ftell()返回一个long(不能保证你的int将保存一个long值)。

希望有所帮助!