[英]How to read structures from a file into an array, modify it and write it back?
I hope the title is correct, i cant describe it better, sorry.我希望标题是正确的,我无法更好地描述它,抱歉。 I have a struct with pointers thats propagated during the "session" of a program.
我有一个带有在程序“会话”期间传播的指针的结构。 Of course, this structure is thrown everytime so i want to save the current state to a binary file.
当然,每次都会抛出这个结构,所以我想将当前状态保存到一个二进制文件中。 Because entry:data is a pointer to an array of unknown length, i tried to append the length to each entry.
因为 entry:data 是一个指向未知长度数组的指针,所以我尝试将长度附加到每个条目。 So far everything is working fine, but when i want to delete or append an antry i run into problems.
到目前为止一切正常,但是当我想删除或附加一个 antry 时,我遇到了问题。 I want to create an array of (struct entry) with the length thats in the file header but as soon as i create the struct the function doesnt work anymore.
我想创建一个(结构体条目)的数组,其长度在文件头中,但是一旦我创建了结构体,该函数就不再起作用了。
Here is a minimal working example这是一个最小的工作示例
#include <stdio.h>
#include <string.h>
struct header {
int id;
int len;
};
struct entry {
int id;
int len; // length of data
char *data;
};
void createNewStorage() {
FILE *f = fopen("test.bin", "wb");
// create a header with id=1 and len=2
struct header hdr = {1, 2};
fwrite(&hdr, sizeof(struct header), 1, f);
char *data;
data = "This is some data of unknown length, i hope it works";
int id = 1;
int len = strlen(data);
struct entry e = {id, len, data};
fwrite(&e.id, sizeof(int), 1, f);
fwrite(&e.len, sizeof(int), 1, f);
fwrite(e.data, sizeof(char), strlen(e.data), f);
id = 2;
data = "\x01\x12\x23";
len = strlen(data);
e.id = id;
e.data = data;
e.len = len;
fwrite(&e.id, sizeof(int), 1, f);
fwrite(&e.len, sizeof(int), 1, f);
fwrite(e.data, sizeof(char), e.len, f);
fclose(f);
}
void appendNewEntry() {
FILE *f = fopen("test.bin", "rb");
// get the header
struct header hdr;
fread(&hdr.id, sizeof(int), 1, f);
fread(&hdr.len, sizeof(int), 1, f);
printf("hdr: id='%d', len='%d'\n", hdr.id, hdr.len);
// get the entries
int id, len = 0; char *data;
int i = 0;
while(i < hdr.len) {
fread(&id, sizeof(int), 1, f);
fread(&len, sizeof(int), 1, f);
fread(&data, sizeof(char), len, f);
printf("entry: id='%d', len='%d', data='%s'\n", id, len, &data);
i++;
}
printf("Done..\n");
fclose(f);
}
int main(void){
createNewStorage();
appendNewEntry();
return 0;
}
Thank you in advance.先感谢您。
Edit : Finally i got it working, here is the final code.编辑:最后我让它工作了,这是最终的代码。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct header {
int id;
int len;
};
struct entry {
int id;
int len; // length of data
char *data;
};
void create() {
FILE *f = fopen("test.bin", "wb");
// create a header with id=1 and len=2
struct header hdr = {1, 2};
fwrite(&hdr, sizeof(struct header), 1, f);
char *data;
data = "This is some data of unknown length, i hope it works";
int id = 1;
int len = strlen(data);
struct entry e = {id, len, data};
fwrite(&e.id, sizeof(int), 1, f);
fwrite(&e.len, sizeof(int), 1, f);
fwrite(e.data, sizeof(char), strlen(e.data), f);
id = 2;
data = "\x01\x12\x23";
len = strlen(data);
e.id = id;
e.data = data;
e.len = len;
fwrite(&e.id, sizeof(int), 1, f);
fwrite(&e.len, sizeof(int), 1, f);
fwrite(e.data, sizeof(char), e.len, f);
fclose(f);
}
void modify() {
FILE *f = fopen("test.bin", "rb");
// get the header
struct header hdr;
fread(&hdr.id, sizeof(int), 1, f);
fread(&hdr.len, sizeof(int), 1, f);
printf("Reading storage hdr: id='%d', len='%d' ", hdr.id, hdr.len);
// create a new list to store all existing entries
struct entry list[hdr.len];
// get the entries
int id, len = 0; char *data;
int i = 0;
while(i < hdr.len) {
fread(&id, sizeof(int), 1, f);
fread(&len, sizeof(int), 1, f);
data = malloc((len + 1) * sizeof(char));
fread(data, sizeof(char), len, f);
data[len] = '\0';
//printf("entry: id='%d', len='%d', data='%s'\n", id, len, &data[0]);
struct entry e = {id, len, data};
list[i] = e;
i++;
}
printf("Done..\n");
printf("The list has %d entries\n", i);
int il = 0;
while(il < i) {
printf("entry %d: len='%d', data='%s'\n", il, list[il].len, list[il].data);
il++;
}
fclose(f);
}
void append(char *newdata) {
printf("Appending new data..\n");
FILE *f = fopen("test.bin", "rb");
// get the header
struct header hdr;
fread(&hdr.id, sizeof(int), 1, f);
fread(&hdr.len, sizeof(int), 1, f);
printf("Reading storage hdr: id='%d', len='%d' ", hdr.id, hdr.len);
// create a new list to store all existing entries
struct entry list[hdr.len];
// get the entries
int id, len = 0; char *data;
int i = 0;
while(i < hdr.len) {
fread(&id, sizeof(int), 1, f);
fread(&len, sizeof(int), 1, f);
data = malloc((len + 1) * sizeof(char));
fread(data, sizeof(char), len, f);
data[len] = '\0';
//printf("entry: id='%d', len='%d', data='%s'\n", id, len, &data[0]);
struct entry e = {id, len, data};
list[i] = e;
i++;
}
printf("Done..\n");
/*
printf("The list has %d entries\n", i);
int il = 0;
while(il < i) {
printf("entry %d: len='%d', data='%s'\n", il, list[il].len, list[il].data);
il++;
}
*/
fclose(f);
f = fopen("test.bin", "wb");
struct header outhdr = {hdr.id, hdr.len+1};
fwrite(&outhdr, sizeof(struct header), 1, f);
int il = 0;
while(il < i) {
printf("writing entry %d\n", il, list[il].len, list[il].data);
fwrite(&list[il].id, sizeof(int), 1, f);
fwrite(&list[il].len, sizeof(int), 1, f);
fwrite(&list[il].data[0], sizeof(char), list[il].len, f);
il++;
}
il++;
struct entry e;
int nid = il;
int nlen = strlen(newdata);
e.id = nid;
e.data = newdata;
e.len = nlen;
printf("writing new entry\n");
fwrite(&e.id, sizeof(int), 1, f);
fwrite(&e.len, sizeof(int), 1, f);
fwrite(e.data, sizeof(char), e.len, f);
fclose(f);
}
void erase(int entryId) {
printf("Appending new data..\n");
FILE *f = fopen("test.bin", "rb");
// get the header
struct header hdr;
fread(&hdr.id, sizeof(int), 1, f);
fread(&hdr.len, sizeof(int), 1, f);
printf("Reading storage hdr: id='%d', len='%d' ", hdr.id, hdr.len);
// create a new list to store all existing entries
struct entry list[hdr.len];
// get the entries
int id, len = 0; char *data;
int i = 0;
while(i < hdr.len) {
fread(&id, sizeof(int), 1, f);
fread(&len, sizeof(int), 1, f);
data = malloc((len + 1) * sizeof(char));
fread(data, sizeof(char), len, f);
data[len] = '\0';
//printf("entry: id='%d', len='%d', data='%s'\n", id, len, &data[0]);
struct entry e = {id, len, data};
list[i] = e;
i++;
}
printf("Done..\n");
/*
printf("The list has %d entries\n", i);
int il = 0;
while(il < i) {
printf("entry %d: len='%d', data='%s'\n", il, list[il].len, list[il].data);
il++;
}
*/
fclose(f);
f = fopen("test.bin", "wb");
struct header outhdr = {hdr.id, hdr.len-1};
fwrite(&outhdr, sizeof(struct header), 1, f);
int il = 0;
while(il < i) {
if(list[il].id == entryId) {
// this is the one to delete
//printf("THIS IS IT -> %d\n", il);
} else {
printf("writing entry %d\n", il, list[il].len, list[il].data);
fwrite(&list[il].id, sizeof(int), 1, f);
fwrite(&list[il].len, sizeof(int), 1, f);
fwrite(&list[il].data[0], sizeof(char), list[il].len, f);
}
il++;
}
}
int main(void){
create();
getch();
char *input;
input = "Mein Hund ist der aller aller Beste";
append(input);
getch();
erase(1);
return 0;
}
Try this:尝试这个:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct header {
int id;
int len;
};
struct entry {
int id;
int len; // length of data
char *data;
};
void createNewStorage() {
FILE *f = fopen("test.bin", "wb");
// create a header with id=1 and len=2
struct header hdr = {1, 2};
fwrite(&hdr, sizeof(struct header), 1, f);
char *data;
data = "This is some data of unknown length, i hope it works";
int id = 1;
int len = strlen(data);
struct entry e = {id, len, data};
fwrite(&e.id, sizeof(int), 1, f);
fwrite(&e.len, sizeof(int), 1, f);
fwrite(e.data, sizeof(char), strlen(e.data), f);
id = 2;
data = "\x01\x12\x23";
len = strlen(data);
e.id = id;
e.data = data;
e.len = len;
fwrite(&e.id, sizeof(int), 1, f);
fwrite(&e.len, sizeof(int), 1, f);
fwrite(e.data, sizeof(char), e.len, f);
fclose(f);
}
void appendNewEntry() {
FILE *f = fopen("test.bin", "rb");
// get the header
struct header hdr;
fread(&hdr.id, sizeof(int), 1, f);
fread(&hdr.len, sizeof(int), 1, f);
printf("hdr: id='%d', len='%d'\n", hdr.id, hdr.len);
// get the entries
int id, len = 0; char *data;
int i = 0;
while(i < hdr.len) {
fread(&id, sizeof(int), 1, f);
fread(&len, sizeof(int), 1, f);
data = malloc((len + 1) * sizeof(char));
fread(data, sizeof(char), len, f);
data[len] = '\0';
printf("entry: id='%d', len='%d', data='%s'\n", id, len, data);
i++;
}
printf("Done..\n");
fclose(f);
}
int main(void){
createNewStorage();
appendNewEntry();
return 0;
}
Output输出
hdr: id='1', len='2'
entry: id='1', len='52', data='This is some data of unknown length, i hope it works'
entry: id='2', len='3', data='#'
Done..
Note笔记
I had to add #inlude <stdlib.h>
to use malloc
.我必须添加
#inlude <stdlib.h>
才能使用malloc
。 The original code was using &data
in fread
and printf
unnecessarily.原始代码在
fread
和printf
不必要地使用&data
。 Also, it does not look like the data is actually read into a list of entry
, which seems odd.此外,看起来数据实际上并没有被读入一个
entry
列表,这看起来很奇怪。
Warning警告
This code allocates memory and it is the users responsibility to free the memory before the program ends.此代码分配内存,用户有责任在程序结束前释放内存。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.