在Objective-C中保存空白文件

我正在研究一个代码,除其他外,必须保存一个零填充文件。 它可以创建一个10MB到1GB空白的文件。

它必须类似于这个Unix命令:

dd if=/dev/zero of=my_image.dsk count=20480 

我可以做一个小尺寸的工作:

 int totalSize = 1024*1024; char buf[totalSize]; strcpy(buf,""); NSData *theData = [NSData dataWithBytes:buf length:sizeof(buf)]; //NSLog(@"%@", theData); NSLog(@"%lu", sizeof(buf)); [theData writeToFile:@"/Users/foo/Desktop/my_image.dsk" atomically:YES]; 

但是,如果我尝试更大的值(例如1024 * 1024 * 10),它会崩溃。 所以我尝试过:

 NSFileManager *ddd = [[NSFileManager alloc ] init]; [ddd createFileAtPath:@"/Users/foo/Desktop/my_image.dsk" contents:[NSData data] attributes:nil]; 

它创建一个空文件,但不好,因为文件大小为零。 它不应该是零。

我花了好几个小时试图找到答案但没有成功。 我想在Obj-C中做到这一点,但在我疯了之前,C也是一个选择。

拜托,有人给我点亮了!

提前致谢!

– 编辑 –

谢谢大家,但还有一件事:是否可以在不分配内存的情况下进行编写?

你可以用dd 。 这将允许您编写例如10 GB而无需担心内存或地址空间。

 NSTask *task = [NSTask new]; long size = ...; // Note! dd multiplies this by 512 by default NSString *path = ...; [task setLaunchPath:@"/bin/dd"]; [task setArguments:[NSArray arrayWithObjects:@"dd", @"if=/dev/zero", [NSString stringWithFormat:@"of=%s", [path fileSystemRepresentation]], [NSString stringWithFormat:@"count=%ld", size], nil]]; [task launch]; [task waitUntilExit]; if ([task terminationStatus] != 0) { // an error occurred... } [task release]; 

一个优点是复杂的用户可以在出现问题时杀死dd

关于沙盒:我怀疑即使在沙箱中这也能正常工作,但我很想知道肯定。 根据文档( 链接 ),子进程“只是inheritance创建它的进程的沙箱”。 这正是您期望它在Unix上运行的方式。

你可以肯定dd会坚持下去,因为Apple声称OS X符合SUSv3。

这在POSIX API中相对简单:

 int f = open("filename", O_CREAT|O_EXCL, S_IRUSR|S_IWUSR); if (f < 0) { perror("open filename"); exit(1); } char empty = 0; pwrite(f, &empty, sizeof(char), ); 

使用off_t的整数指定偏移量,该整数可能不足以满足您的特定需求。 检查系统API文档以发现64位文件接口(如果它不够大)。

这种方法的最好的部分是它只需要几个字节的程序存储器 – 你没有分配10千兆字节的任何东西来编写你的文件。

另一种更简单的方法是使用truncate(2)系统调用。 并非所有平台都支持使用truncate(2)扩展文件,但对于那些支持扩展文件,它只能进行一次调用

试试这段代码:

 int totalSize = 1024*1024; // don't allocate on the stack char *buf = calloc(totalSize, sizeof(char)); NSData *theData = [NSData dataWithBytesNoCopy:buf length:totalSize]; //NSLog(@"%@", theData); NSLog(@"%lu", totalSize); [theData writeToFile:@"/Users/foo/Desktop/my_image.dsk" atomically:YES]; 

您也可以尝试这样做,减少内存耗费,并使用1 GB文件。

 void writeBlankBytes(FILE *file, size_t numKB) { static char *oneKBZero = NULL; if (oneKBZero == NULL) { oneKBZero = calloc(1024, sizeof(char)); } for (int i = 0; i < numKB; i++) { fwrite(oneKBZero, 1, 1024, file); } } 

感谢大家。 我找到了解决方案。 这基本上是我将要放入cocoa应用程序的代码草图。

工作正常,我认为我只需要一些尺寸变量的预防措施,这就足够了。

 long size = 2000*500; NSString *path = [[NSString alloc] initWithFormat: @"/Users/foo/Desktop/testeFile.dsk"]; NSTask *task = [[NSTask alloc] init]; [task setLaunchPath:@"/bin/dd"]; [task setArguments:[NSArray arrayWithObjects: @"if=/dev/zero", [NSString stringWithFormat:@"of=%s", [path fileSystemRepresentation]], [NSString stringWithFormat:@"count=%ld", size], nil]]; NSLog(@"%@",[task arguments]); [task launch]; //[task waitUntilExit]; //The app would stuck here.. better use the loop int cont = 0; while ([task isRunning]) { cont++; if(cont%100==0) NSLog(@". %d", cont); } if ([task terminationStatus] != 0) { NSLog(@"an error occurred..."); } [task release]; [path release]; NSLog(@"Done!");