使用C从.DAT文件读取char *类型时出错

时间:2012-11-15 07:53:32

标签: c fread

因此,出于某种原因,我需要创建一个外部文件(.DAT)来存储数据,方法是将新数据附加到旧数据的末尾。

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

int main () {
    typedef struct {
        char *Name;
        int Index;
    } DataFile;

    static FILE *file;
    size_t result;
    DataFile *DataTable;

    file = fopen("database.DAT","ab");
    DataTable = (DataFile *) malloc (sizeof(DataFile));
    DataTable[0].Name = "somefile.txt";
    DataTable[0].Index = 7;
    printf("%s %d \n",DataTable[0].Name,DataTable[0].Index);
    result = fwrite(DataTable,sizeof(DataFile),1,file);
    fclose(file);
    free(DataTable);
    return 0;
}

运行上面的代码后,我检查数据是否存储正确。所以,我在下面编写了这段代码。

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

int main () {
    typedef struct {
        char *Name;
        int Index;
    } DataFile;

    static FILE *file;
    size_t result;
    long size;
    int i;
    DataFile *DataTable;

    file = fopen("database.DAT","rb");
    if (file == NULL) printf("Error1");

    // Determine the size of file
    fseek(file,0,SEEK_END);
    size = ftell(file);
    rewind(file);

    DataTable = (DataFile *) malloc ((size/sizeof(DataFile)) * sizeof(DataFile));
    if (DataTable == NULL) printf("Error2");

    result = fread(DataTable,sizeof(DataFile),size/sizeof(DataFile),file);
    fclose(file);

    for (i=0; i<result; i++) {
        printf("%s %d \n",DataTable[i].Name,DataTable[i].Index);
    }
    free(DataTable);
    return 0;
}

但是,它提供了输出

somefile.txt 7

来自第一个代码块和

Error1 7

来自第二个代码块。 我注意到问题不是因为在打开.DAT文件或为DataTable分配内存时失败。此外,它适用于int类型(索引),但不适用于从.DAT文件读取时的char *类型(名称)。我不知道如何解决这个char * -type-reading问题(以及'error1'来自哪里)。 (甚至不是谷歌给我回答。)

3 个答案:

答案 0 :(得分:2)

您的结构DataFile存储一个指针和一个整数。当您将其写入文件时,您可以编写一些特定于程序的字符串指针和一个整数。

从中读取时,只需用指针和整数重新填充结构,这意味着DataFile.Name将成为指向可能未初始化的内存段的指针。但是,由于您创建了指向第一个硬编码字符串("filename.txt")的文件,因此会发生一些未定义但可理解的行为,并且在这种情况下您的指针指向您在第二个程序中编写的第一个硬编码字符串(在你的情况下是Error1

您真正想要做的是在文件中写下真实的字符串。

一个简单的解决方案,如果你想保持洞写结构的事情是创建一个数组而不是一个指针

typedef struct {
        char Name[512];
        int Index;
    } DataFile;

然后使用

初始化您的数据
strncpy(DataTable[0].Name, "somefile.txt", sizeof(DataTable[0].Name) - 1); // just to make sure you dont overflow your array size
DataTable[0].Name[sizeof(DataTable[0].Name) - 1] = '\0';

以您的方式重新审核您的数据。

答案 1 :(得分:1)

char*只是一个指针,即包含字符串的字符数组的地址。您不会将字符串本身写入文件。读取文件后,由于相同的字符串不再存在于同一地址的内存中,应用程序将失败。

您必须想出一种将字符串本身保存到文件的方法。可能首先写下他们的长度,然后写出他们的内容。在读取时,您可以使用长度信息动态分配内存,然后读入该内存。

答案 2 :(得分:0)

在您的编写代码中,您尚未为char *Name分配存储空间。当您执行DataTable[0].Name = "somefile.txt"指令时,实际上并未将"somefile.txt"复制到Name指向的内存中,它实际上正在为Name指定一个指向常量字符串的值(此外,它将成为悬空指针,因为字符串是一个右值,即没有要通过的内存来解决)。您的文件读取代码也是如此。 你需要:

  1. Name分配存储空间。
  2. 使用memcpy或类似字符串将字符串复制到已分配的存储空间中。