gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 04:59:25 27 4
gpt4 key购买 nike

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

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

当前代码:

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

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

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

最佳答案

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

If the mode string includes a plus sign, then the mode allows both input and output, and you must synchronize the file position indicator between reading from and writing to the file. Do this by calling fflush() or a file positioning function -- fseek(), fsetpos(), or rewind() -- after writing and before reading, and by calling a file-positioning function after reading and before writing (unless it is certain that you have read to the end of the file).



问题出在您嵌套最多的 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 值)。

希望有帮助!

关于c - 更新包含 c 中结构的二进制文件,偏移更改为损坏文件的其余部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16327416/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com