2013-05-13 30 views
10

我试图用C代码生成大文件(4-8 GB)。 现在我使用fopen()'wb'参数来打开文件二进制和fwrite()函数在for循环中将字节写入文件。我在每次循环迭代中写入一个字节。在文件大于或等于4294967296字节(4096 MB)之前没有问题。它看起来像32位操作系统中的一些内存限制,因为当它写入该打开的文件时,它仍然在RAM中。我对吗?症状是创建的文件比我想要的尺寸小。差别是4096MB,例如当我需要6000 MB文件时,它会创建6000 MB - 4096 MB = 1904 MB文件。32位系统上的大文件的fwrite()替代

你能否建议其他方式来完成这项任务?

问候:)

的代码部分:

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

'i'是如何定义的? – willys 2013-05-13 10:28:45

+3

'strcat(argv [3],“。bin”)'wrong – BLUEPIXY 2013-05-13 10:29:16

+0

@willys'i' is definied this way:'unsigned long long int i = 0;' – bLAZ 2013-05-13 10:30:12

回答

2

fwrite这里不是问题。问题是您正在计算的值为number_of_data

在处理64位整数时,您需要小心任何无意的32位转换。当我定义他们,我通常做了一些不连续的步骤,注意每一步:赋值运算符(*=)将作用于L值(在unsigned long long int

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 

,所以你可以相信它是在64位值上进行操作的。

这可能看起来没有优化,但体面的编译器会删除任何不必要的步骤。

+0

这个解决方案帮助了我:)这确实是这个变量值的问题。但非常感谢所有回答这个问题的人。这非常有用和信息丰富。 – bLAZ 2013-05-13 18:50:25

2

你不应该有任何问题,在Windows上创建大量文件,但我注意到,如果你使用的是32位版本的征求文件它似乎决定它是一个32位文件,因此不能大于4GB。在Windows上处理大于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++怪癖)。

UPDATE

原来的问题是使用连续的输出值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; 
} 

然而,这将是真的是慢,因为我们一次只写一个字节。这可以通过使用更大的缓冲区或通过在描述符(fd)上调用fdopen并切换到fwrite来使用缓冲I/O来改善。

+0

你的MSVC++怪癖在MinGW(-w64)GCC下也能正常工作;他们是Windows C运行时库的怪癖,而不是编译器。 – rubenvb 2013-05-13 11:37:15

+0

也许这就是我要找的东西,但我离“Hello World”不远,现在很难以我想要的方式使用它:D请给我一点时间。 – bLAZ 2013-05-13 11:47:35

+0

@patthoyts你能告诉我如何给该函数的文件名? – bLAZ 2013-05-13 11:57:18

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无论你的目标变量有多大。

+0

所以这就是为什么我得到了溢出警告。但它现在告诉我,'atoll'是未定义的:/我有'#包括< stdlib.h >'。 – bLAZ 2013-05-13 12:38:32

+1

尝试#include 并使用_strtoui64(或_tcstoui64如果使用TCHAR类型)。 – patthoyts 2013-05-13 13:50:24

+0

明天我会尝试这个解决方案,但它可能会像@Lee Netherton解决方案(同样的问题问题)一样帮助。谢谢。 – bLAZ 2013-05-13 18:56:54

相关问题