如何在C++中将结构体写入文件并读取文件?

4
我有一个结构体,并使用write()将其写入文件。
struct PointFull {
    double lat;
    double lon;
};

PointFull item;
void* buffer = malloc(sizeof (item));
int fd = open("output", O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR);
if (fd < 0) {
    printf("Error opening file\n");
    return 1;
}
memcpy(buffer, &item, sizeof (item));
write(fd2, buffer, sizeof (item));

现在我在硬盘上有一个名为"output"的文件,然后我想读取这个文件来测试数据。
int fd2 = open("output", O_RDONLY, S_IWUSR | S_IRUSR);
if (fd2 < 0) {
    printf("Error opening file\n");
    return 1;
}
void* bufferRead;
bufferRead = malloc(100);
read(fd2, bufferRead,100);

目前,我有bufferRead,但我不知道如何读取缓冲区并将数据插入到结构体中。

您可以直接读取或写入item,无需通过中间缓冲区。 - Jonathan Potter
2
首先,我认为在C++中使用malloc的合法用例并不多,甚至可能没有。 - Carcigenicate
2
你想学习C还是C++? - Beta
1
@Carcigenicate:我知道一个。如果分配失败,malloc将返回一个空指针,这很容易测试;防范构造函数失败则要麻烦得多。 - Beta
@Beta 很酷。不过你能不能直接从“new”中捕获异常呢?我认为处理起来不会更加复杂。 - Carcigenicate
显示剩余6条评论
4个回答

4

由于您标记了C ++

#include <iostream>
#include <fstream>
using namespace std;

struct PointFull {
    double lat;
    double lon;

    PointFull(double lat_in = 0, double lon_in = 0) 
        : lat(lat_in), lon(lon_in) {}
};

int main() {
    PointFull item(123123, 123123);

    cout << "Writing to disk" << endl;
    ofstream fout("saved_point.txt");
    fout << item.lat << ' ' << item.lon;
    fout.close();

    cout << "Reading from disk" << endl;
    PointFull item_from_disk;
    ifstream fin("saved_point.txt");
    fin >> item_from_disk.lat >> item_from_disk.lon;
    fin.close();

    cout << "From RAM and then disk" << endl;
    cout << item.lat << ' ' << item.lon << endl;
    cout << item_from_disk.lat << ' ' << item_from_disk.lon << endl;


    return 0;
}

谢谢您的回复。使用fd和ofstream有什么不同?我认为fd更快。如果我仍然使用缓冲区,如何从缓冲区读取数据? - Mozart
6
当我的结构体有100个成员时,这不是一个好的解决方案... - Zac

3
  1. 你最好分配一个大小为sizeof(PointFull)的缓冲区。因为如果结构体的大小发生变化并且变得大于你硬编码的大小,那么你将会遇到一个bug。
  2. 除非你真正需要动态内存,否则请使用本地缓冲区。我假设在你的代码中你并不真正需要一个分配。只是你可能会轻易忘记释放内存,而当函数返回时,缓冲区会自动被删除。
int fd2 = open("output", O_RDONLY, S_IWUSR | S_IRUSR);
if (fd2 < 0) {
    printf("Error opening file\n");
    return 1;
}
char bufferRead[sizeof(PointFull)];
read(fd2, bufferRead, sizeof(bufferRead));
//Now as you've read it, just cast the memory to struct, and assign it
item = *reinterpret_cast<PointFull*>(bufferRead);
//okay, now item holds the file content, you no longer need the buffer

此外注意:您的结构体可能通过插入填充来对齐。尽管我不认为PointFull会出现这种情况,但是当您需要像这样序列化结构时,最好使用#pragma pack声明它以不允许填充。例如:
#pragma pack(push, 1) // exact fit - no padding
struct PointFull {
    double lat;
    double lon;
};
#pragma pack(pop) //back to whatever the previous packing mode was

2
  • You can use fwrite and fread to write data into file and read from file.
    Below is sample code for same.

     #include <stdio.h>
    
     struct PointFull
     {
        int number;
        char text[10];
        double real_number;
     };
    
     int main()
    {
     struct PointFull  data = {1, "Hello!", 3.14159}, read_data;
     FILE *fout = fopen("file_path", "w");
     fwrite(&data, sizeof(PointFull ), 1, fout);
     //   fprintf(fout, "%d %s %f",data.number, data.text, data.real_number);
     fclose(fout);
    
     FILE* fin = fopen("file_path", "r");
     fread(&read_data, sizeof(PointFull ), 1, fin);
     printf("%d %s %lf\n", read_data.number, read_data.text, read_data.real_number);
     fclose(fin);
     return 0;
    }
    
    • If u use fwrite data will be written in binary or ascii format.To read that data u have to use fread.
    • If u use fprintf and fscanf ,data will be stored in human redable format.

感谢您的回答。您的方法更易于操作,但我想知道使用fd进行写入和读取是否比使用fread fwrite更快? - Mozart
@MaiNhậtTân 这是可移植性与安全性的问题。可以查看:fwrite() 是标准的一部分,因此在任何平台上都受支持;但 write() 不受支持。另一方面,像 fwrite() 这样的 C-API 使用指针,因此您有可能遇到某处的 nullptr 引用,这将导致崩溃。类似 write() 的 Posix 函数没有这个问题。 - Hi-Angel

-1
有一个名为“drake”的MIT图书馆具有这个功能。您需要采取一些步骤来序列化结构,但他们的文档似乎非常好!

我不认为这回答了这个问题。虽然不是我给的负评,但如果我还有更多机会,我会加一个。 - starball

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接