0

I'm trying to write a C structure in a file (to write in binary) and read it to recover it. I don't know if it is possible. Here is what I have :

head.hh:

#include <iostream>

typedef struct s_test
{
  char  cmd[5];
  std::string   str;
}t_test;

main.cpp:

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "head.hh"

int     main()
{
  t_test        test;
  int   fd = open("test", O_APPEND | O_CREAT | O_TRUNC | O_WRONLY, 0666);

  test.cmd[0] = 's';
  test.cmd[1] = 'm';
  test.cmd[2] = 's';
  test.cmd[3] = 'g';
  test.str = "hello world";
  write(fd, &test, sizeof(t_test));


  close(fd);
  fd = open("test", O_APPEND | O_CREAT | O_WRONLY, 0666);

  t_test        test2;

  read(fd, &test2, sizeof(t_test));
  std::cout << test2.cmd << " " << test2.str << std::endl;

  return (0);
}

And on the output I have something like : Ȟ�

Elfayer
  • 4,411
  • 9
  • 46
  • 76
  • 2
    You can't read/write a `std::string` that way, you'll need to serialize the data one member at a time. – Retired Ninja Nov 14 '13 at 18:09
  • This is not going to work without serialization – drescherjm Nov 14 '13 at 18:09
  • Use "basic" types, that means, not object in the struct and then you will be able to do that with char, int, float. If you use an object you will not be able to get the real size inside it – Lefsler Nov 14 '13 at 18:45
  • Possible duplicate of [How to read / write a struct in Binary Files?](https://stackoverflow.com/questions/5506645/how-to-read-write-a-struct-in-binary-files) – underscore_d Dec 15 '17 at 13:46

2 Answers2

1

The file to read from was being opened as write only.

The actual std::string object can't be written that way. The actual object generally contains a couple of pointers and perhaps a size but not the actual character data. It need to be serialized.

If you're going to be writing C++ you should consider learning to use file streams rather than what you've got here.

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <io.h>
#include <iostream>
#include <string>
#include <vector>

typedef struct s_test
{
    char cmd[5];
    std::string str;
}t_test;

void Write(int fd, struct s_test* test)
{
    write(fd, test->cmd, sizeof(test->cmd));
    unsigned int sz = test->str.size();
    write(fd, &sz, sizeof(sz));
    write(fd, test->str.c_str(), sz);
}

void Read(int fd, struct s_test* test)
{
    read(fd, test->cmd, sizeof(test->cmd));
    unsigned int sz;
    read(fd, &sz, sizeof(sz));
    std::vector<char> data(sz);
    read(fd, &data[0], sz);
    test->str.assign(data.begin(), data.end());
}

int main()
{
    t_test test;
    int fd = open("test", O_APPEND | O_CREAT | O_TRUNC | O_WRONLY, 0666);

    test.cmd[0] = 's';
    test.cmd[1] = 'm';
    test.cmd[2] = 's';
    test.cmd[3] = 'g';
    test.cmd[4] = 0;
    test.str = "hello world";
    std::cout << "Before Write: " << test.cmd << " " << test.str << std::endl;

    Write(fd, &test);
    close(fd);

    fd = open("test", O_RDONLY, 0666);
    t_test test2;
    Read(fd, &test2);
    std::cout << "After Read: " << test2.cmd << " " << test2.str << std::endl;
    close(fd);

    return (0);
}
Retired Ninja
  • 4,785
  • 3
  • 25
  • 35
0

See when you dump an structure into binary file its in memory image gets written on disk for example:

class X
{
public:
    int i;
    int j;
};

. . .

X lX;
lX.i= 10;
lX.j = 20;

an object of class lX when written into a binary file will look something like |10|20| i.e when you'll read it will work fine.

but for a class which contains any pointer like string does.

class Y
{
public:
    int* pi;
    int j;
};

. . .

Y lY;
lY.pi= new int(10); // lets assume this is created at memory location 1001
lY.j = 20;

so object lY will have value of pi as 1001 (not 10, as it is a pointer). now when you write lY to a binary file it will look like |10001|20| and when you'll read it back it will construct new object of Y (say lY2 )having values pi to be 1001 and j to be 20. Now we what do pi(which is a pointer) points to?? answer is garbage, that is something you are looking on screen. I guess you are using Windows to run this as Linux would have given you a segmentation fault.

Shubham
  • 172
  • 8