我正在尝试使用C代码生成大文件(4-8 GB)。
现在我使用带有fopen()
参数的'wb'
来打开fwrite()
循环中的文件二进制和for
函数,以便将字节写入文件。我在每次循环迭代中写一个字节。在文件大于或等于4294967296字节(4096 MB)之前没有问题。它看起来像32位操作系统中的一些内存限制,因为当它写入打开的文件时,它仍然在RAM中。我对吗?症状是创建的文件比我想要的更小。差异是4096 MB,例如当我想要6000 MB文件时,它会创建6000 MB - 4096 MB = 1904 MB文件。
你能建议其他方法来完成这项任务吗?
问候:)
部分代码:
unsigned long long int number_of_data = (unsigned int)atoi(argv[1])*1024*1024; //MB
char x[1]={atoi(argv[2])};
fp=fopen(strcat(argv[3],".bin"),"wb");
for(i=0;i<number_of_data;i++) {
fwrite(x, sizeof(x[0]), sizeof(x[0]), fp);
}
fclose(fp);
答案 0 :(得分:2)
在Windows上创建大文件时不应该有任何问题,但我注意到如果你在文件上使用32位版本的搜索,那么它似乎决定它是一个32位文件,因此不能大于4GB。在Windows上使用&gt; 4GB文件时,我已成功使用_open,_lseeki64和_write。例如:
static void
create_file_simple(const TCHAR *filename, __int64 size)
{
int omode = _O_WRONLY | _O_CREAT | _O_TRUNC;
int fd = _topen(filename, omode, _S_IREAD | _S_IWRITE);
_lseeki64(fd, size, SEEK_SET);
_write(fd, "ABCD", 4);
_close(fd);
}
以上将创建超过4GB的文件而不会出现问题。但是,它可能很慢,因为当你调用_write()时,文件系统必须为你实际分配磁盘块。如果必须随机填充,您可能会发现创建稀疏文件的速度更快。如果您将从头开始按顺序填充文件,那么上面的代码就可以了。请注意,如果您确实想使用fwrite提供的缓冲IO,则可以使用fdopen()从C库文件描述符中获取FILE *。
(如果有人想知道,TCHAR,_topen和下划线前缀都是MSVC ++怪癖)。
<强>更新强>
最初的问题是对N个字节的值V使用顺序输出。因此,一个应该实际产生所需文件的简单程序是:
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <io.h>
#include <tchar.h>
int
_tmain(int argc, TCHAR *argv[])
{
__int64 n = 0, r = 0, size = 0x100000000LL; /* 4GB */
char v = 'A';
int fd = _topen(argv[1], _O_WRONLY | _O_CREAT| _O_TRUNC, _S_IREAD | _S_IWRITE);
while (r != -1 && n < count) {
r = _write(fd, &v, sizeof(value));
if (r >= 0) n += r;
}
_close(fd);
return 0;
}
然而,由于我们一次只写一个字节,因此真的慢。通过在描述符(fd)上调用fdopen并切换到fwrite,可以通过使用更大的缓冲区或使用缓冲的I / O来改善这一点。
答案 1 :(得分:2)
fwrite
不是问题所在。问题是您为number_of_data
计算的值。
在处理64位整数时,需要注意任何无意的32位转换。当我定义它们时,我通常会在许多不连续的步骤中完成它,每一步都要小心:
unsigned long long int number_of_data = atoi(argv[1]); // Should be good for up to 2,147,483,647 MB (2TB)
number_of_data *= 1024*1024; // Convert to MB
赋值运算符(*=
)将作用于l值(unsigned long long int
),因此您可以信任它对64位值起作用。
这可能看起来没有经过优化,但是一个不错的编译器会删除任何不必要的步骤。
答案 2 :(得分:1)
Yuo fwrite()
没问题。问题似乎是你的
unsigned long long int number_of_data = (unsigned int)atoi(argv[1])*1024*1024; //MB
确实应该像
uint16_t number_of_data = atoll(argv[1])*1024ULL*1024ULL;
unsigned long long
仍然没问题,但无论您的目标变量有多大,unsigned int * int * int
都会给您一个unsinged int
。