将链表(包含动态字符串)保存(和读取)到 C 中的二进制文件中

Saving (and reading) Linked List (that containts dynamic strings) Into Binary File In C

我正在尝试将read/write链表转换成二进制文件,问题是这个链表包含 动态分配的字符串,当我尝试从文件中读取链接列表时,我进入了字符串字段地址而不是字符串值。 有人知道可能是什么问题吗?


    void saveProject(FrameNode* headFrame, char* filePath)
    {
    FILE* projectFile = fopen(filePath, WRITING_MODE);
    FrameNode* currentFrame = headFrame;
    if (projectFile) // making sure the fopen() didn't failed
    {
        while (currentFrame != NULL) // making sure the list isn't empty
        {
            fseek(projectFile, 0, SEEK_END); // writing the node to the end of the file
            // writing the currentNode into the file and returning the value of ->"next"
            fwrite(currentFrame->frame, sizeof(Frame), 1, projectFile);
            currentFrame = currentFrame->next; // moving to the next frame
        }
        fseek(projectFile, 0, SEEK_SET); // returning the seek of the file to the start
        fclose(projectFile);
    }
}


void openProject(FrameNode** headFrame, char* filePath)
{
    FILE* projectFile = fopen(filePath, READING_MODE);
    FrameNode* currentFrame = *headFrame;
    int numOfFrames = 0;
    int i = 0;

    if (projectFile) // making sure the fopen() function didn't failed
    {
        // making sure the headFrame doesn't point to existing list
        dealloc_linked_list(*headFrame);
        *headFrame = NULL;

        // finding the number of nodes (=frames) in the projectFile file
        fseek(projectFile, 0, SEEK_END);
        numOfFrames = (int)(ftell(projectFile) / sizeof(Frame));
        fseek(projectFile, 0, SEEK_SET);

        for (i = 0; i < numOfFrames; i++)
        {
            // reading the next frame in the list
            fseek(projectFile, sizeof(Frame) * i, SEEK_SET);
            addFrameFromFile(headFrame, projectFile);
        }

    }
    fclose(projectFile);
}

void addFrameFromFile(FrameNode** headFrame, FILE* projectFile)
{
    FrameNode* newFrame = NULL;

    if (*headFrame == NULL) // in case the list is empty
    {
        *headFrame = (FrameNode*)malloc(sizeof(FrameNode));
        newFrame = *headFrame;
    }
    else // if the list isn't empty, the function will search for the last node in the list
    {
        newFrame = findLastFrame(*headFrame);
        newFrame->next = (FrameNode*)malloc(sizeof(FrameNode));
        newFrame = newFrame->next;
    }
    
    // adding the data from the file to the newFrame
    newFrame->frame = (Frame*)malloc(sizeof(Frame));
    fread(newFrame->frame, sizeof(Frame), 1, projectFile);

    newFrame->next = NULL; // making the frame be the last in the list
}

这是链表节点结构:

// the content
typedef struct Frame
{
    char* name;
    unsigned int    duration;
    char* path;
} Frame;


// Link (node) struct
typedef struct FrameNode
{
    Frame* frame;
    struct FrameNode* next;
} FrameNode;

当我尝试读取文件时,我得到了下一个输出: click me to see the screenshot of the output 第一个打印是我写入文件的原始列表,第二个是我使用 openProject() 函数从文件创建的列表。

提前致谢

fwrite() 函数用于将程序中活动 RAM 中的二进制值写入文件,因此当您调用 fwrite(currentFrame->frame,sizeof(Frame),1,projectFile) 时,您要求系统复制 sizeof(Frame)(乘以一个)字节从 currentFrame->frame 指向的内存到你的文件中。

在你的设置中,一个 Frame 里面有两个 char*,但是 fwrite 不关心这个。 fwrite() 函数将像对待任何其他二进制值一样对待这些指针,并将很快就会不正确的内存地址复制到文件中。

如果您想将链表的重要部分保存到一个文件中,以便将来可以使用相同的数据重新生成一个链表,您需要将字符串的内容实际复制到文件中,就像这样:

void saveProject(FrameNode* headFrame, char* filePath)
{
    FILE* projectFile = fopen(filePath, WRITING_MODE);
    FrameNode* currentFrame = headFrame;
    if (projectFile == NULL) // making sure the fopen() didn't failed
        return;
    while (currentFrame != NULL) // making sure the list isn't empty
    {
            fprintf(projectFile,"%s%d%s",currentFrame->frame->name,currentFrame->frame->duration,currentFrame->frame->path);
            currentFrame = currentFrame->next; // moving to the next frame
    }
    fclose(projectFile);
}

fprintf() 的工作方式与 printf 类似,除了它写入文件而不是 stdout,因此它将字符串写入文件而不是指向它们的指针。

请注意,代码中的所有 fseek 都是不必要的,因为文件光标会在您写入文件时自动移动。

要从文件中再次生成新的链表,您可以在循环中使用 fscanf(),但请确保在从文件中复制字符串时为字符串分配内存。

关于;

typedef struct Frame
{
    char* name;
    unsigned int    duration;
    char* path;
} Frame;

 fwrite(currentFrame->frame, sizeof(Frame), 1, projectFile);

fwrite() 的调用正在输出 Frame 实例的内容,但是,这不会输出要在指针指向的位置找到的数据。

此外,在写出这些指针后,尝试将它们读回,指针现在毫无意义。

建议修改 typedef ... Frame 以实际包含数据而不是指向数据的指针。

建议:

typedef struct Frame
{
    char name[ MAX_NAME_LEN ];
    unsigned int    duration;
    char path[ MAX_PATH_LEN ];
} Frame;   

除了获取 Frame

的实例外,还将消除对 malloc() 和 family 的调用