在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!");