代码之家  ›  专栏  ›  技术社区  ›  Zach M.

fwrite和fread问题

  •  0
  • Zach M.  · 技术社区  · 12 年前

    我的fwrite()和fread()在处理二进制文件时遇到了问题,这是我的源代码,对bottem是我的读写。现在,当我运行它时,它会返回“jake”,而不是其他内容。我被告知要编写一个转储缓冲区函数来处理二进制字符。此外,这里还有文本文件,我正在写一个名为info.bin.PS的空白文件。我知道将zip保存为int是不好的做法,但这正是我的教授所要求的。

    文件:

    mike|203-376-5555|7 Melba Ave|Milford|CT|06461
    jake|203-555-5555|8 Melba Ave|Hartford|CT|65484
    snake|203-555-5555|9 Melba Ave|Stamford|CT|06465
    liquid|203-777-5555|2 Melba Ave|Barftown|CT|32154
    

    代码:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #define LINE 80
    #define RECORDS 10
    
    
    struct info{
      char name[100];
      char number[100];
      char address[100];
      char city[100];
      char state[100];
      int zip;
    };
    
    void dump_buffer(void *buffer, int buffer_size)
    {
      int x;
    
      for(x = 0; x < buffer_size; x++)
      {
        printf("%c",((char *)buffer)[x]);
      }
    }
    
    int i, j, seeker;
    
    int main(int argc, char* argv[])
    {
      char *buffer;
    
      struct info input_records[RECORDS];
      int nrecs = 0;
      unsigned long fileLen;
      char line[LINE];
      FILE *fp = NULL;
      FILE *fpbin = NULL;
      FILE *fpread = NULL;
    
    
    
      if (argc != 2) 
      {
        printf ("ERROR: you must specify file name!\n");
        return 1;
      }
      /* Open file */
      fp = fopen(argv[1], "r");
      if (!fp) 
      {
        perror ("File open error!\n");
        return 1;
      }
    
      while (!feof (fp)) {
        fgets(line, sizeof(line),fp);
        char* tok =  strtok(line, "|");
    
        while(tok != NULL)
        {
          strcpy(input_records[nrecs].name, tok);
          tok = strtok(NULL, "|");
          strcpy(input_records[nrecs].number, tok);
          tok = strtok(NULL, "|");
          strcpy(input_records[nrecs].address, tok);
          tok = strtok(NULL, "|");
          strcpy(input_records[nrecs].city, tok);
          tok = strtok(NULL, "|");
          strcpy(input_records[nrecs].state, tok);
          tok = strtok(NULL, "|");
          input_records[nrecs].zip = atoi(tok);
          tok = strtok(NULL, "|");
        }
        nrecs++;
      }
    
    
    
    
      fpbin = fopen("info2.bin", "wb");
      if (!fp) 
      {
        perror ("File open error!\n");
        return 1;
      }
    
      for(i = 0; i < 4; i++)
      {
    
       fwrite(&input_records[i], sizeof(struct info), 200000, fpbin);
    
      }
    
      fclose(fpbin);
    
    
    
      fpread = fopen("info2.bin", "rb");
    
    
    
      fseek(fpread, 0, SEEK_END);
      fileLen = ftell(fpread);
      fseek(fpread, 0, SEEK_SET);
    
      buffer = (char *)malloc(sizeof(struct info));
    
      fread(buffer, fileLen, 1, fpread);
    
    
      dump_buffer(buffer, sizeof(buffer));
    
      fclose(fpread);
    
      fclose(fp);
      free(buffer);
    return 0;
    }
    
    1 回复  |  直到 12 年前
        1
  •  4
  •   Daniel Fischer    12 年前
    fwrite(&input_records[i], sizeof(struct info), 200000, fpbin);
    

    你刚才说 fwrite 200000 * sizeof(struct info) 字节到文件,从的地址开始 input_records[i] .访问的内存远远超出了已分配的内存 input_records ,行为是未定义的,但分割错误并非不可能。事实上,我很惊讶它没有为你崩溃。

    buffer = (char *)malloc(sizeof(struct info));
    
    fread(buffer, fileLen, 1, fpread);
    

    你正在努力阅读 fileLen 字节放入大小为的缓冲区 sizeof(struct info) 如果 fileLen > sizeof(struct info) ,这也是未定义的行为,如果 文件长度 足够大,很可能会崩溃。

    你应该让 写入文件 大小物体 sizeof(结构信息) 每次,您应该分配 文件长度 您读入的缓冲区的字节数(或读入大小为块的缓冲区) sizeof(结构信息) )。您应该检查的返回值 写入文件 fread 以了解他们是否成功地写入/读取了所需的数据并适当地处理了故障。

    fpbin = fopen("info2.bin", "wb");
    if (!fp) 
    {
    

    你检查错了 FILE* 在这里,而你不检查 fpread 完全

    此外,您将错误的计数传递给 dump_buffer ,

    dump_buffer(buffer, sizeof(buffer));
    

    buffer 是一个 char* 所以 sizeof buffer 是一个的大小 炭* ,通常为四个或八个字节。您应该将分配的缓冲区大小传递到那里。

    并且当读取原始文件时,

    while (!feof (fp)) {
        fgets(line, sizeof(line),fp);
    

    feof(fp) 只有在到达文件末尾时尝试读取后才变为true,您应该将循环条件更改为

    while(fgets(line, sizeof line, fp) != NULL) {
    

    最后,如果输入文件包含格式错误的数据或太长的行,则标记化代码将严重失败。你还应该在那里添加检查,这样你就不会通过 NULL strcpy atoi