将链表(包含动态字符串)保存(和读取)到 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 的调用
我正在尝试将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 的调用