0

我的 fwrite() 和 fread() 处理二进制文件时遇到问题是我的源代码,而最底层是我的读写。现在,当我运行它时,它正在返回“杰克”,没有别的。我被告知要编写一个转储缓冲区函数来处理二进制字符。此外,这里还有文本文件,我正在写入一个名为 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;
}
4

1 回答 1

4
fwrite(&input_records[i], sizeof(struct info), 200000, fpbin);

您刚刚告诉fwrite200000 * sizeof(struct info)字节写入文件,从input_records[i]. 访问的内存远远超出分配的内存input_records,行为未定义,但分段错误并非不可能。我实际上很惊讶它显然没有为你崩溃。

buffer = (char *)malloc(sizeof(struct info));

fread(buffer, fileLen, 1, fpread);

您正在尝试将fileLen字节读入 size 的缓冲区sizeof(struct info)。如果fileLen > sizeof(struct info),那又是未定义的行为,并且如果fileLen足够大,可能会崩溃。

您应该每次都让fwrite 一个大小的对象sizeof(struct info),并且应该fileLen为您读取的缓冲区分配字节(或读取大小的块sizeof(struct info))。并且您应该检查它们的返回值fwritefread了解它们是否成功写入/读取所需数据并适当地处理故障。

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

你在这里检查错FILE*了,你根本不检查fpread

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

dump_buffer(buffer, sizeof(buffer));

buffer是 a char*, asizeof buffer的大小也是如此char*,通常是四个或八个字节。您应该在那里传递分配的缓冲区大小。

而且,在读取原始文件时,

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

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

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

最后,如果输入文件包含格式错误的数据或太长的行,您的标记化代码将严重失败。您还应该在此处添加检查,以免将 a 传递NULLstrcpyor atoi

于 2012-10-01T20:06:50.127 回答