我正在尝试将应用中的图片合并到一个文件中并将其写入磁盘。
NSMutableArray *array = [NSMutableArray arrayWithObjects:
[NSData dataWithContentsOfFile:@"0.png"],
[NSData dataWithContentsOfFile:@"1.png"],
[NSData dataWithContentsOfFile:@"2.png"],
nil];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:array];
NSError *error = nil;
NSString *path=@"/Users/myusername/Desktop/_stuff.dat";
[data writeToFile:path options:NSDataWritingAtomic error:&error];
或
NSArray *array = [NSArray arrayWithObjects:
[NSImage imageNamed:@"0"],
[NSImage imageNamed:@"1"],
[NSImage imageNamed:@"2"],
nil];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:array];
NSError *error = nil;
NSString *path=@"/Users/myusername/Desktop/_stuff.dat";
[data writeToFile:path options:NSDataWritingAtomic error:&error];
但两者都产生一个4KB(空)的文件。如果我NSLog
错误,则为(null)
。我是以错误的方式制作数据吗?
编辑:如果我用文本编辑器打开生成的文件,它看起来像这样:
答案 0 :(得分:4)
我写了一个简单的例子:
缺失:内存管理/错误处理/正确处理文件
// Archive
NSMutableArray *array = [[NSMutableArray alloc] init];
NSString * input = @"/Users/Anne/Desktop/1.png";
[array addObject:[NSData dataWithContentsOfFile:input]];
[array addObject:[NSData dataWithContentsOfFile:input]];
[array addObject:[NSData dataWithContentsOfFile:input]];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:array];
NSString *path = @"/Users/Anne/Desktop/archive.dat";
[data writeToFile:path options:NSDataWritingAtomic error:nil];
// Unarchive
NSMutableArray *archive = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
NSData * firstObject = [archive objectAtIndex:0];
NSString * output = @"/Users/Anne/Desktop/2.png";
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:output];
[firstObject writeToURL:fileURL atomically:YES];
您还可以将NSImages添加到NSMutableArray:
NSString * input = @"/Users/Anne/Desktop/1.png";
NSImage *image = [[NSImage alloc] initWithContentsOfFile: input];
[array addObject:image];
但这会显着增加文件大小。
答案 1 :(得分:4)
回复以下评论:
因此,如果我只需要在运行时(在存档中)访问图像,是否有办法在索引处访问该图像而无需取消归档整个内容?对我来说似乎是不必要的开销。
我认为你还在努力解决这个问题? Hiding (or encrypting) app resources?
就像前面提到的那样,将所有文件合并为一个大文件就可以了 只需确保记住每个文件和文件顺序的文件长度 然后,您可以在不阅读整个文件的情况下提取您喜欢的任何特定文件 如果您当时只需要提取一个文件,这可能是更充分的方法。
快速'脏'样本:
// Two sample files
NSData *fileOne = [NSData dataWithContentsOfFile:@"/Users/Anne/Desktop/1.png"];
NSData *fileTwo = [NSData dataWithContentsOfFile:@"/Users/Anne/Desktop/2.png"];
// Get file length
int fileOneLength = [fileOne length];
int fileTwoLength = [fileTwo length];
// Combine files into one container
NSMutableData * container = [[NSMutableData alloc] init];
[container appendData:fileOne];
[container appendData:fileTwo];
// Write container to disk
[container writeToFile:@"/Users/Anne/Desktop/container.data" atomically:YES];
// Read data and extract sample files again
NSData *containerFile = [NSData dataWithContentsOfFile:@"/Users/Anne/Desktop/container.data"];
NSData *containerFileOne =[containerFile subdataWithRange:NSMakeRange(0, fileOneLength)];
NSData *containerFileTwo =[containerFile subdataWithRange:NSMakeRange(fileOneLength, fileTwoLength)];
// Write extracted files to disk (will be exactly the same)
[containerFileOne writeToFile:@"/Users/Anne/Desktop/1_extracted.png" atomically:YES];
[containerFileTwo writeToFile:@"/Users/Anne/Desktop/2_extracted.png" atomically:YES];
// Only extract one file from the container
NSString * containerPath = @"/Users/Anne/Desktop/container.data";
NSData * oneFileOnly = [[NSFileHandle fileHandleForReadingAtPath:containerPath] readDataOfLength:fileOneLength];
// Write result to disk
[oneFileOnly writeToFile:@"/Users/Anne/Desktop/1_one_file.png" atomically:YES];
提示:
您还可以将“索引”保存在容器文件中
例如:前500个字节包含所需信息
当您需要特定文件时:阅读索引,获取文件位置并将其解压缩。
答案 2 :(得分:1)
您正在归档NSImage的NSMutable数组。这两个类符合NSKeyedArchiver所要求的NSCoding协议,所以我看不出你的问题在哪里。
所以,这里有很多想法要测试。
首先,您确定您认为自己拥有的数据有效吗?在您的第一个代码段中,您可以编写[NSData dataWithContentsOfFile:@"0.png"]
。此方法需要绝对文件路径。
假设问题不在你的代码中,只是在你的问题中,让我们继续:
归档后,您在变量数据中是否有不同于nil的内容?即,在分配数据之后,您可以添加此代码。如果断言失败,您将在运行时获得异常:
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:array];
NSAssert(nil != data, @"My object data is nil after archiving");
如果问题不在这里,那么[data writeToFile:path options:NSDataWritingAtomic error:&error];
行的回报是什么?
(不是变量错误,而是对方法- writeToFile: options: error:
的调用的返回值)
如果您简化代码并执行此操作会发生什么:
result = [NSKeyedArchiver archiveRootObject:data
toFile:archivePath];
如果一切正常,您是否尝试使用NSKeyedUnarchiver取消归档文件?
答案 3 :(得分:1)
问题是[NSData dataWithContentsOfFile:@"0.png"]
在当前目录中查找文件“0.png”,但是应用程序认为当前目录可能不是您期望的位置。对于图形应用程序,您应始终使用绝对路径或相对于某些可获取绝对路径的位置的路径(例如,您的应用程序包,应用程序支持目录,某些用户选择的位置)。
对于命令行工具,使用当前目录更为常见。但我怀疑是这种情况。
答案 4 :(得分:0)
我在小牛队注意到的另一件事是路径中的文件夹必须存在。这意味着您必须在保存到该文件夹之前创建文件夹结构。如果您尝试写入桌面或其他地方的文件夹,即使关闭了沙盒,如果该文件夹不存在,也会失败。我知道这已经得到了解答,但我发现我的问题仍然存在,但是一旦我确保文件夹结构到位,我就可以写到该文件夹了。
旁注:我确信你可以从NSFileManager那里做到这一点,一旦我最终确定我的应用程序结构,我将自己这样做,但希望这可以帮助其他人迷失方向。