注册 登录
编程论坛 C语言论坛

求教高手,关于二进制文件读写问题

huangzhenfan 发布于 2012-07-21 10:46, 870 次点击
问题:把一个整数插入到一个记录了若干整数的二进制文件的前部
想法:
假设被插入的整数记录在变量 int i;中
先取出文件中第一个整数存放在变量int t;中
向文件写入 i 的值,然后
i=t;
再从文件中取出第二个整数存放在变量int t;中
向文件写入 i 的值,然后
i=t;
……
依此类推
最后当fread返回值为0时
再写一个数就OK

下面是代码
先预备一个二进制文件#include <stdlib.h>

#include <stdio.h>
int main( void )
{
  FILE *pf=NULL;
  int i = 100 , t ;
  pf = fopen("abc","wb");
  fwrite(&i,sizeof(int),1,pf);
  fclose(pf);
  return 0;
}

复制代码为简单起见,文件里只写了一个整数
下面开始读写
#include <stdlib.h>
#include <stdio.h>
int main( void )
{
  FILE *pf=NULL;
  int i = 99 , t ;
//  pf = fopen("abc","wb");
//  fwrite(&i,sizeof(int),1,pf);
//  fclose(pf);
  pf = fopen("abc","rb+");
  while( fread(&t,sizeof(int),1,pf) ) //读一个数放在t中
  {
      fseek(pf,-(long)sizeof(int) ,SEEK_CUR);//退回原来的位置
      fwrite(&i,sizeof i,1,pf) ;              //写入i
      i = t ;                                //留着下次写入
  }
  fseek(pf,-(long)sizeof(int) ,SEEK_CUR);
  fwrite(&i,sizeof i,1,pf);
  fclose(pf);
  return 0;
}
复制代码结果竟是死循环

很想听听大家对这个BUG的高见
9 回复
#2
netlin2012-07-21 12:03
楼主的思路挺好的!

 while( fread(&t,sizeof(int),1,pf) ) //读一个数放在t中
  {
      fseek(pf,-(long)sizeof(int) ,SEEK_CUR);//退回原来的位置
      fseek(pf,-sizeof(int) ,SEEK_CUR);//换成这句,看看!
      fwrite(&i,sizeof i,1,pf) ;              //写入i
      i = t ;                                //留着下次写入
  }
  fseek(pf,-(long)sizeof(int) ,SEEK_CUR);
  fwrite(&i,sizeof i,1,pf);
(这两句不能再这么写了,直接写一条语句:在最后面添加i值即可。)
  fclose(pf);
  return 0;
}
#3
TonyDeng2012-07-21 18:26
思路不是这样的。而且你叙述的思路也不是把数据插在前面呀。
#4
LShang2012-07-21 20:30
我想的是读取文件到内存,插入后再重写文件,效率貌似不高。。。
#5
TonyDeng2012-07-21 20:40
跟文件的内容和被插入的数据有关系。效率不好说,超大的文件,读入内存再写就不是那么好了。具体情形具体分析吧。
#6
LShang2012-07-21 20:44
回复 5楼 TonyDeng
恩恩 不能太死板,灵活运用
#7
TonyDeng2012-07-21 21:00
最稳妥保险的做法,是新建一个文件,先把要插入的数据写入,然后把原来的文件追加到后面去。用C直接处理可以,用操作系统的文件合并也可以。这样无论是写还是读,都是单方向扫一遍的,尽量回避把文件指针移来移去,那种定位很不靠谱,变数太多。对大文件,要测试环境的效率,找出每次读写的数据块是多大,1024K还是4096K甚至更大,不同的操作系统这是不同效果的。如果是特大文件,在Windows下可以用MappingFile功能把文件映射为内存,直接用内存的复制和移动操作,数G的文件也不成问题。
#8
TonyDeng2012-07-21 23:12
楼主的代码被局限在特定的数据类型中,我给你一个不限的,用4楼的方法:

程序代码:

#include <cstdio>
#include <cstdlib>

bool CreateNewFile(const char* filename);

void main(void)
{
    const char str[] = "Hello, world!";
    const char filename[] = "test.dat";

    CreateNewFile(filename);

    FILE* file;
    if ((fopen_s(&file, filename, "rb") == 0) && (fseek(file, 0, SEEK_END) == 0))
    {
        long file_size = ftell(file);
        fseek(file, 0, SEEK_SET);
        char* memory = NULL;
        if ((memory = (char*) malloc(file_size * sizeof(char))) != NULL)
        {
            fread(memory, file_size, 1, file);
        }
        if (freopen_s(&file, filename, "wb", file) == 0)
        {
            fwrite(str, sizeof(str), 1, file);
            if (memory != NULL)
            {
                fwrite(memory, file_size, 1, file);
            }
        }
        fclose(file);
        free(memory);
        memory = NULL;
    }
}

bool CreateNewFile(const char* filename)
{
    FILE* file;
    errno_t err = fopen_s(&file, filename, "wb");
    if (errno == 0)
    {
        for (int number = 0; number < 1024; ++number)
        {
            fwrite(&number, sizeof(number), 1, file);
        }
        fclose(file);
    }

    return (errno == 0);
}


[ 本帖最后由 TonyDeng 于 2012-7-21 23:14 编辑 ]
#9
TonyDeng2012-07-21 23:17
1楼代码的bug,根据文档介绍,似乎应该在移动文件指针进行读写之前先调用fflush()刷新数据。
#10
huangzhenfan昨天 09:15
谢谢,各位大虾,老式C语言的BUG,在文件读写函数直接切换时需要用fflush()刷新, 可能是缓冲区没有满或没有刷新,临时内存数据还没有一起写入到文件
1