C语言 将数组写入二进制文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21213543/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 10:38:40  来源:igfitidea点击:

Write array into the binary file?

cfile-io

提问by erthalion

I need some help - next piece of code writes a long double dynamic array into the file

我需要一些帮助 - 下一段代码将一个长双动态数组写入文件

int nx = 10, ny = 10;
long double **data = new long double *[nx]; 
long double **data_read = new long double *[nx]; 
for (int i = 0; i < nx; i++) {
    data[i] = new long double [ny];
    data_read[i] = new long double [ny];
}

data[4][4] = 10.0;
printf("%LF\n", data[4][4]);

FILE *file = fopen("data", "wb");
fwrite(data, nx * ny * sizeof(data), 1, file);
fclose(file);

file = fopen("data", "rb");
fread(data, nx * ny * sizeof(data_read), 1, file );
fclose(file);

printf("%LF\n", data_read[4][4]);

But data[4][4] != data_read[4][4], because after reading from file data_read[4][4]=0.0.

但是data[4][4] != data_read[4][4],因为从文件读取后data_read[4][4]=0.0

Anybody knows what am I doing wrong?

有谁知道我做错了什么?

回答by WhozCraig

You need to write each row in your pointer array individually. A mass write will not work for pointer-to-pointer implementations of a fake 2D array (or nD).

您需要单独写入指针数组中的每一行。批量写入不适用于伪二维数组(或 nD)的指针到指针实现。

For writing:

对于写作:

for (int i=0; i<nx; ++i)
    fwrite(data[i], sizeof(data[i][0]), ny, file);

For reading:

阅读:

for (int i=0; i<nx; ++i)
    fread(data[i], sizeof(data[i][0]), ny, file);

Frankly, you're (un)fortunate the process didn't crash outright, as you were writing a bunch of memory addresses to your disk file (which a hex dump would have showed you), and were likely walking off the end of your pointer-array allocation during bothoperations.

坦率地说,您(不)幸运的是该进程没有彻底崩溃,因为您正在将一堆内存地址写入您的磁盘文件(十六进制转储会向您展示),并且很可能走开了两个操作期间的指针数组分配。

That said, I'd start learning about the standard C++ IO library rather than using C-code in a C++ world (or fix the tag on this question).

也就是说,我将开始学习标准 C++ IO 库,而不是在 C++ 世界中使用 C 代码(或修复这个问题的标签)。



Single Block Write/Read

单块写/读

You asked if it is possible to do this as a single block read/write. The answer is yes, but you must allocate the memory contiguously. If you still want a pointer-to-pointer array you can certainly use one. Though I recommend using std::vector<long double>for the data buffer, the following will demonstrate what I refer to:

您询问是否可以将其作为单个块读/写来执行。答案是肯定的,但您必须连续分配内存。如果您仍然想要一个指向指针的数组,您当然可以使用一个。尽管我建议将其std::vector<long double>用于数据缓冲区,但以下内容将演示我所指的内容:

int main()
{
    int nx = 10, ny = 10;

    long double *buff1 = new long double[nx * ny];
    long double *buff2 = new long double[nx * ny];

    long double **data = new long double *[nx];
    long double **data_read = new long double *[nx];

    for (int i = 0; i < nx; i++)
    {
        data[i] = buff1 + (i*ny);
        data_read[i] = buff2 + (i*ny);
    }

    data[4][4] = 10.0;
    printf("%LF\n", data[4][4]);

    FILE *file = fopen("data.bin", "wb");
    fwrite(buff1, sizeof(*buff1), nx * ny, file);
    fclose(file);

    file = fopen("data.bin", "rb");
    fread(buff2, sizeof(*buff2), nx * ny, file );
    fclose(file);

    printf("%LF\n", data_read[4][4]);

    // delete pointer arrays
    delete [] data;
    delete [] data_read;

    // delete buffers
    delete [] buff1;
    delete [] buff2;
}

Output

输出

10.000000
10.000000


Using a std::vector<>for an RAIISolution

使用std::vector<>一个RAII解决方案

All those allocations can get messy, and frankly prone to problems. Consider how this is different:

所有这些分配都会变得混乱,坦率地说容易出现问题。考虑一下这有什么不同:

#include <iostream>
#include <fstream>
#include <vector>

int main()
{
    int nx = 10, ny = 10;

    // buffers for allocation
    std::vector<long double> buff1(nx*ny);
    std::vector<long double> buff2(nx*ny);

    // holds pointers into original
    std::vector<long double*> data(nx);
    std::vector<long double*> data_read(nx);

    for (int i = 0; i < nx; i++)
    {
        data[i] = buff1.data() + (i*ny);
        data_read[i] = buff2.data() + (i*ny);
    }

    data[4][4] = 10.0;
    std::cout << data[4][4] << std::endl;

    std::ofstream ofp("data.bin", std::ios::out | std::ios::binary);
    ofp.write(reinterpret_cast<const char*>(buff1.data()), buff1.size() * sizeof(buff1[0]));
    ofp.close();

    std::ifstream ifp("data.bin", std::ios::in | std::ios::binary);
    ifp.read(reinterpret_cast<char*>(buff2.data()), buff2.size() * sizeof(buff2[0]));
    ifp.close();

    std::cout << data_read[4][4] << std::endl;

    return 0;
}

回答by herohuyongtao

Change your code to (see comments for details):

将您的代码更改为(有关详细信息,请参阅注释):

...
data[4][4] = 10.0;
printf("%Lf\n", data[4][4]); // use %Lf to print long double, not %LF

FILE *file = fopen("data", "wb"); 
for (int i=0; i<nx; ++i) // must write row-by-row as data are not continuous
    fwrite(data[i], sizeof(long double), ny, file); 
      // cannot use sizeof(data) here as data is a pointer here, will always return 4
fclose(file);

file = fopen("data", "rb");
for (int i=0; i<nx; ++i)  // read row-by-row
    fread(data_read[i], sizeof(long double), ny, file); 
      // 1. read to data_read, not data
      // 2. cannot use sizeof(data) here as data is a pointer here, will always return 4
fclose(file);

printf("%Lf\n", data_read[4][4]);  // use %Lf to print long double, not %LF
...


Edit:

编辑:

If you want to format the data in a continuous memory, use vector<long double>or long double data[nx*ny]instead. Then you can easily write or read by:

如果要在连续内存中格式化数据,请使用vector<long double>long double data[nx*ny]代替。然后,您可以通过以下方式轻松编写或阅读:

fwrite(data, nx * ny * sizeof(long double), 1, file);
...
fread(data_read, nx * ny * sizeof(long double), 1, file );