在文件中逐行存储一个巨大的数组会导致文件损坏

Storing a huge array in a file, row by row, results in a damaged file

我在内存中存储了一个输入数组A,用于生成另一个数组,更大的B。但是,由于B是一个巨大的数组,我真的不想将它存储在内存中,但要将其保存到本地文件中(使用 fwrite)。为此,我计算每个迭代 ith 行并将其附加到输出文件。这样,我一次只需要在内存中存储一​​行,最终会创建一个输出文件,其中包含我需要的所有数据。

考虑到输出文件包含的项目数量,输出文件的大小似乎合适。然而,当我尝试使用 fread 从输出文件中读回片段时(例如,检索前 2000 项),仅检索到前 23 项。

这是创建输出文件的主要函数:

void exportCovMatrix(char *outputString, double *inputStdMatrix, int colDim, int rowDim) {
    double *covRow = calloc(rowDim, sizeof(double));
    int i, j, n;
    FILE *output;
    fclose(fopen(outputString, "w"));
    output = fopen(outputString, "a");
    assert(covRow != NULL);
    assert(output != NULL);
    for (i = 0; i < rowDim; i++) {
        for (j = 0; j < rowDim; j++)
            covRow[j] = dotProduct(&inputStdMatrix[i * colDim], &inputStdMatrix[j * colDim], colDim);
        n = fwrite(covRow, sizeof(double), rowDim, output);
        assert(n == rowDim);
    }
    fclose(output);
    free(covRow);
}

这是另一个函数,它读取给定的输出文件:

double *calculateNextB(char* inputString, double* row, int dim){
    FILE* input = fopen(inputString, "r");
    int i, j;
    assert(input != NULL);
    for(i = 0; i <= dim; i++){
        j = fread(row, sizeof(double), dim, input);
        printf("%d items were read.\n", j);
    }
    ...
}

对于解决此问题的任何帮助,我将不胜感激。谢谢!

您分别用

打开文件
fclose(fopen(outputString, "w"));

FILE* input = fopen(inputString, "r");

但正如所解释的那样 here

In order to open a file as a binary file a "b" character has to be included in the mode string.

(我知道它是 C++ 源代码,但在某些系统中确实如此,尽管在许多 POSIX 系统中并不如此,如 https://linux.die.net/man/3/fopen 中所述)

我假设文件很大。

在“a”32“bits”系统上,流相关函数(fopen、fwrite 等)限制为 2GiB。超过这个尺寸,功能的效果未定义。

请参考此页。

https://www.gnu.org/software/libc/manual/html_node/Opening-Streams.html#index-fopen64-931

也参考这个问题


关于这个(略有修改的)建议代码:

  1. 正确检查错误
  2. 避免在(可能)生产代码中使用 assert()
  3. 计算每一行数据,然后将该行写入文件。
  4. 每次调用此函数时将文件大小设置回 0 长度。
  5. 正确表示该文件是 'binary' 文件而不是 'text' 文件。
  6. 由于 'nothing' 函数无法编译:dotproduct()
  7. 不知道inputStdMatrix[ rowDim ][ colDim ]
  8. 中每一行的长度
  9. 这个参数:double *inputStdMatrix不应该写成:double inputStdMatrix[][ colDim ],参数rowDimcolDim在这个参数
  10. 之前
  11. 适当限制局部变量的'scope'

现在,建议的代码:

#include <stdio.h>
#include <stdlib.h>


void exportCovMatrix(char *outputString, size_t colDim, size_t rowDim, double inputStdMatrix[][ colDim ], ) 
{
    double *covRow = calloc(rowDim, sizeof(double));
    if( ! covRow )
    {
        perror( "calloc for row of data failed" );
        exit( EXIT_FAILURE );
    }

    FILE *output;
    output = fopen(outputString, "wb");
    if( ! output )
    {
        perror( "fopen for write binary file failed" );
        free( covRow );  // cleanup
        exit( EXIT_FAILURE );
    }

    // assert(covRow != NULL);
    // assert(output != NULL);

    for ( size_t i = 0; i < rowDim; i++) 
    {
        for ( size_t j = 0; j < rowDim; j++)
        {
            covRow[j] = dotProduct(&inputStdMatrix[i * colDim],
                                   &inputStdMatrix[j * colDim], 
                                    colDim);
        }

        size_t n = fwrite(covRow, sizeof(double), rowDim, output);
        // assert(n == rowDim);
        if( n != rowDim )
        {
            // handle error of short write
        }
    }

    fclose(output);
    free(covRow);
}

只将 rowDim 行写入文件。

然后,如果再次调用它,它会删除文件中的内容。可能不是你想要的。