在文件中逐行存储一个巨大的数组会导致文件损坏
Storing a huge array in a file, row by row, results in a damaged file
我在内存中存储了一个输入数组A,用于生成另一个数组,更大的B。但是,由于B是一个巨大的数组,我真的不想将它存储在内存中,但要将其保存到本地文件中(使用 fwrite
)。为此,我计算每个迭代 i
th 行并将其附加到输出文件。这样,我一次只需要在内存中存储一行,最终会创建一个输出文件,其中包含我需要的所有数据。
考虑到输出文件包含的项目数量,输出文件的大小似乎合适。然而,当我尝试使用 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
也参考这个问题
关于这个(略有修改的)建议代码:
- 正确检查错误
- 避免在(可能)生产代码中使用
assert()
- 计算每一行数据,然后将该行写入文件。
- 每次调用此函数时将文件大小设置回 0 长度。
- 正确表示该文件是 'binary' 文件而不是 'text' 文件。
- 由于 'nothing' 函数无法编译:
dotproduct()
- 不知道
inputStdMatrix[ rowDim ][ colDim ]
中每一行的长度
- 这个参数:
double *inputStdMatrix
不应该写成:double inputStdMatrix[][ colDim ]
,参数rowDim
和colDim
在这个参数 之前
- 适当限制局部变量的'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
行写入文件。
然后,如果再次调用它,它会删除文件中的内容。可能不是你想要的。
我在内存中存储了一个输入数组A,用于生成另一个数组,更大的B。但是,由于B是一个巨大的数组,我真的不想将它存储在内存中,但要将其保存到本地文件中(使用 fwrite
)。为此,我计算每个迭代 i
th 行并将其附加到输出文件。这样,我一次只需要在内存中存储一行,最终会创建一个输出文件,其中包含我需要的所有数据。
考虑到输出文件包含的项目数量,输出文件的大小似乎合适。然而,当我尝试使用 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
也参考这个问题
关于这个(略有修改的)建议代码:
- 正确检查错误
- 避免在(可能)生产代码中使用
assert()
- 计算每一行数据,然后将该行写入文件。
- 每次调用此函数时将文件大小设置回 0 长度。
- 正确表示该文件是 'binary' 文件而不是 'text' 文件。
- 由于 'nothing' 函数无法编译:
dotproduct()
- 不知道
inputStdMatrix[ rowDim ][ colDim ]
中每一行的长度
- 这个参数:
double *inputStdMatrix
不应该写成:double inputStdMatrix[][ colDim ]
,参数rowDim
和colDim
在这个参数 之前
- 适当限制局部变量的'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
行写入文件。
然后,如果再次调用它,它会删除文件中的内容。可能不是你想要的。