在写入文件并在c

时间:2017-02-14 17:34:03

标签: c fwrite fread

我正在尝试使用fread和fwrite来读取和写入与文件中的结构有关的数据。这是我的代码:

#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<string.h>

typedef struct book book;

struct book
{
char title[200];
char auth[200];
char publi[200];
int p_year;
int price;
int edition;
int isbn;
};

int main()
{
    int i;
    FILE* fp = fopen("this.dat","w");
    book * a = calloc(1000000,sizeof (book));

    srand(time(NULL));

    for(i=0;i<1000000;i++)
    {
        a[i].price = rand()%1000;
        a[i].p_year = 1500 + rand()%518;
        a[i].isbn = 10000+rand()%100000;
        a[i].edition = i%15;

        strcpy(a[i].title,"title");
        strcpy(a[i].auth,"author");
        strcpy(a[i].publi,"publication");
    }

    if((i=fwrite(a,sizeof(*a),1000000,fp))!= 1000000)
    {
        printf("ERROR - Only %d records written\n",i);
        printf("feof:%d\nferror:%d",feof(fp),ferror(fp));
        return EXIT_FAILURE;
    }

    if(ferror(fp))
    {
        printf("ERROR");
        return EXIT_FAILURE;
    }

    if(fclose(fp)!=0)
    {
        printf("ERROR while closing the stream");
        return EXIT_FAILURE;
    } 

    if((fp = fopen("this.dat","r")) == NULL)
    {
        printf("ERROR reopening");
        return EXIT_FAILURE;
    }

    if((i=fread(a,sizeof(book),100,fp))!=100)
    {
        printf("ERROR - Only %d records read\n",i);
        printf("feof:%d\nferror:%d",feof(fp),ferror(fp));
        return EXIT_FAILURE;
    }

    if(ferror(fp))
    {
        printf("~ERROR");
        return EXIT_FAILURE;
    }

    for(i=0;i<100;i++)
        printf("price:%d\nedition:%d\nisbn:%d\np_year:%d\n\n\n",a[i].price,a[i].edition,a[i].isbn,a[i].p_year);


    fclose(fp);
    return EXIT_SUCCESS;
    }

事情偶尔会成功执行,但大部分时间都没有。使用fread从文件读回时出错。它最终每次读取可变数量的记录,并且记录的数量少于它应该记录的数量(即100)。以下是该程序执行失败的输出之一:

错误 - 只读了25条记录 FEOF:16
ferror:0

问题1 :为什么eof在写入超过25个时只读取了25条记录? (我在重新打开文件后尝试使用rewind / fseek,但问题仍然存在。)

问题2 :在这种情况下,a(&lt; 1)}之后,a[x-1]以外的数组x中包含的数据被篡改是否正常? 100)记录被读取?即使成功读取了100条记录,数据是否仍会被篡改超过a[99](我知道数据被篡改,因为尝试打印a元素之外的数组xth元素的字段会导致不合适的值,例如价格&gt; 1000或价格&lt; 0等等)

1 个答案:

答案 0 :(得分:1)

在读取/写入二进制结构时,您不应该以文本模式打开文件。

虽然它对Linux / Unix没有影响,但在Windows上会产生严重后果。它使您的文件在Windows和Linux之间不可共享。

取决于数据LF&lt; =&gt; CR / LF转换可能损坏/移位数据(删除回车或插入一个)

在Windows的文本模式下,写入时每个LF(ASCII 10)字节被CR + LF(13 + 10 ASCII)字节替换(读取时反向:13 + 10 => 10)。这些10个字节可能发生,例如在将1802年(十六进制:0x70A)写为二进制时。

解决方案:使用二进制模式:

if((fp = fopen("this.dat","rb")) == NULL)

FILE* fp = fopen("this.dat","wb");

注意:&#34; text&#34;模式,指定块大小不起作用,因为大小取决于数据。这可能回答了你的第二个问题:最后100条记录读取已损坏,因为你读的字节太少了。我不确定细节,但由于系统在写/读时添加/删除字节,因此块大小可能有问题。