写作“打包”;使用 C 构造文件

发布于 2024-09-13 10:35:06 字数 218 浏览 6 评论 0原文

如何使用 C 将结构“打包”和“写入”到文件中,以便:

struct a {
    uint64_t a;
    char* b;
    uint16_t c;
} a;
a b;
b.a = 3;
b.b = "Hello";
b.c = 4;

写入文件

00 00 00 00 00 00 00 03 48 65 6c 6c 6f 00 00 04

How can I "pack" and "write" a struct to a file using C so that:

struct a {
    uint64_t a;
    char* b;
    uint16_t c;
} a;
a b;
b.a = 3;
b.b = "Hello";
b.c = 4;

gets written to the file as

00 00 00 00 00 00 00 03 48 65 6c 6c 6f 00 00 04

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

风吹短裙飘 2024-09-20 10:35:06

在 C 中,您必须编写一个函数来为您完成此操作。您不能只是将结构复制到磁盘,因为 b 是一个没有支持字符串就没有任何意义的指针。而且,除非您知道(并且可以控制)编译器如何打包其结构,否则即使没有指针,您最好还是使用实用函数。

而且,好像这还不够,您还应该输出字符串的长度,以便您知道要读回多少字节。

你会寻找类似的东西:

int better_than_blat (FILE *f, struct a *x) {
    size_t len = strlen (x->b);
    if (fwrite (&(x->a), sizeof(long), 1, f) != 1) return -1;
    if (fwrite (&len, sizeof(size_t), 1, f) != 1) return -1;
    if (fwrite (x->b, len, 1, f) != 1) return -1;
    if (fwrite (&(x->c), sizeof(short), 1, f) != 1) return -1;
    return 0;
}

int better_than_unblat (FILE *f, struct a *x) {
    size_t len;
    if (fread (&(x->a), sizeof(long), 1, f) != 1) return -1;
    if (fread (&len, sizeof(size_t), 1, f) != 1) return -1;
    x->b = malloc (len + 1);
    if (x->b == NULL) return -1;
    memset (x->b, 0, len + 1);
    if (fread (x->b, len, 1, f) != 1) return -1;
    if (fread (&(x->c), sizeof(short), 1, f) != 1) return -1;
    return 0;
}

In C, you'll have to code a function to do this for you. You can't just blat the structure out to disk because b is a pointer that makes no sense without the backing string. And, unless you know (and can control) how your compiler packs its structures, you're better off with a utility function anyway, even without pointers.

And, as if that wasn't enough, you should output the length of the string as well so you know how many bytes to read back.

You'll be looking for something like:

int better_than_blat (FILE *f, struct a *x) {
    size_t len = strlen (x->b);
    if (fwrite (&(x->a), sizeof(long), 1, f) != 1) return -1;
    if (fwrite (&len, sizeof(size_t), 1, f) != 1) return -1;
    if (fwrite (x->b, len, 1, f) != 1) return -1;
    if (fwrite (&(x->c), sizeof(short), 1, f) != 1) return -1;
    return 0;
}

int better_than_unblat (FILE *f, struct a *x) {
    size_t len;
    if (fread (&(x->a), sizeof(long), 1, f) != 1) return -1;
    if (fread (&len, sizeof(size_t), 1, f) != 1) return -1;
    x->b = malloc (len + 1);
    if (x->b == NULL) return -1;
    memset (x->b, 0, len + 1);
    if (fread (x->b, len, 1, f) != 1) return -1;
    if (fread (&(x->c), sizeof(short), 1, f) != 1) return -1;
    return 0;
}
烟雨凡馨 2024-09-20 10:35:06

您必须编写自己的方式来序列化这些数据;编译器不会为您提供处理字符串的内置方法。那里有序列化库,但我不知道任何直接 C 语言的库。

但是,请考虑使用更结构化的方法来序列化数据,例如 json 或 xml。即使是 INI 文件也比原始二进制转储更好。这样做的原因是:

  • 更容易调试
  • 更向前兼容
  • 不太严格/容易出错
  • 如果您使用现有的库,那么您将获得与之相关的社区的回报。
  • 现有的库可能支持您稍后会摸不着头脑的功能,例如数组
  • 更好的跨平台兼容性。

you must write your own way to serialize this data; the compiler won't hand you a built-in way to deal with the string. There are serialization libraries out there but I don't know any for straight C.

But, consider using a more structured method for serializing data, such as json or xml. Even an INI file is better than raw binary dump. Reasons for this are:

  • easier to debug
  • more forward compatible
  • less rigid / error-prone
  • if you use an existing library, then you reap the rewards of the community that goes with it.
  • an existing library is likely to support features that you will later scratch your head over like arrays
  • better cross platform compatibility.
一影成城 2024-09-20 10:35:06

以下内容会有帮助吗?

struct buffer {

  char bytes[1000];
  int nbytes;
};

struct buffer *new_buffer(){
  struct buffer b = (struct buffer*) malloc(sizeof(struct buffer));
  b->nbytes = 0;
  return b;
}

void append_long(struct buffer *b, long *l){
  memcpy(b->bytes + b->nbytes, l);
  b->nbytes += sizeof(*l);
}

// ...and so on for other types

void fwrite_buffer(FILE *fp, struct buffer *b){
  fwrite(b->bytes, sizeof(*b), 1, fp);
}

用法:

struct buffer *buf = new_buffer();
struct a b;
b.a = 3;
b.b = "Hello";
b.c = 4;
append_long(buf, &(b.a));
append_pointer(buf, &(b.b));
append_short(buf, &(b.b));
fwrite_buffer(fp, buf);

Will the following help?

struct buffer {

  char bytes[1000];
  int nbytes;
};

struct buffer *new_buffer(){
  struct buffer b = (struct buffer*) malloc(sizeof(struct buffer));
  b->nbytes = 0;
  return b;
}

void append_long(struct buffer *b, long *l){
  memcpy(b->bytes + b->nbytes, l);
  b->nbytes += sizeof(*l);
}

// ...and so on for other types

void fwrite_buffer(FILE *fp, struct buffer *b){
  fwrite(b->bytes, sizeof(*b), 1, fp);
}

Usage:

struct buffer *buf = new_buffer();
struct a b;
b.a = 3;
b.b = "Hello";
b.c = 4;
append_long(buf, &(b.a));
append_pointer(buf, &(b.b));
append_short(buf, &(b.b));
fwrite_buffer(fp, buf);
人事已非 2024-09-20 10:35:06

如果您不在结构中使用指针并且显式定义打包对齐方式,则可以安全地将结构打包到字节数组中。

例如(海湾合作委员会):

struct a {
    long a;
    char b[256];
    short c;
}  __attribute__((__packed__));

int size = sizeof(a);
void* buffer = malloc(size);
memcpy(buffer, (void*)a, size);

You can safely pack your structure into byte array, if you will not use pointers in it and will explicitly define packing alignment.

For example (gcc):

struct a {
    long a;
    char b[256];
    short c;
}  __attribute__((__packed__));

int size = sizeof(a);
void* buffer = malloc(size);
memcpy(buffer, (void*)a, size);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文