我正在尝试用C代码生成大文件(4-8 GB)。现在,我使用带有'wb'参数的fopen()打开文件二进制文件,并在for循环中使用fwrite()函数将字节写入文件。我在每次循环迭代中写入一个字节。除非文件大于或等于4294967296字节(4096MB),否则没有问题。它看起来像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);发布于 2013-05-13 21:45:04
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位值。
这看起来可能并不优化,但一个好的编译器会删除任何不必要的步骤。
发布于 2013-05-13 19:03:30
你在Windows上创建大文件应该不会有任何问题,但我注意到,如果你在文件上使用32位版本的seek,那么它似乎会决定它是一个32位文件,因此不能大于4 4GB。我已经成功地使用了_open,_lseeki64和_write,在Windows上处理大于4 4GB的文件。例如:
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);
}以上将创建一个超过4 4GB的文件而不会出现问题。但是,它可能会很慢,因为当您在那里调用_write()时,文件系统必须为您实际分配磁盘块。如果必须随机填充稀疏文件,您可能会发现创建稀疏文件会更快。如果您将从开头按顺序填充文件,那么上面的代码就可以了。注意,如果您真的想使用fwrite提供的缓冲IO,那么可以使用fdopen()从C库文件描述符中获取一个FILE*。
(如果有人想知道,TCHAR、_topen和下划线前缀都是MSVC++的怪癖)。
更新
最初的问题是对值为V的N个字节使用顺序输出。因此,应该实际生成所需文件的简单程序是:
#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;
}然而,这将是非常慢的,因为我们一次只写一个字节。这可以通过使用更大的缓冲区或使用缓冲I/O来改进,方法是在描述符(fd)上调用fdopen并切换到fwrite。
发布于 2013-05-13 20:29:38
你对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。
https://stackoverflow.com/questions/16519834
复制相似问题