macos 写入文件不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5171095/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Write to file not working
提问by sudo rm -rf
I'm trying to combine images in my app into one file and write it to disk.
我正在尝试将应用程序中的图像合并到一个文件中并将其写入磁盘。
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];
or
或者
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];
But both produce a file that is 4KB (empty). If I NSLog
the error it is (null)
. Am I making the data the wrong way?
但两者都会产生一个 4KB(空)的文件。如果我NSLog
的错误是(null)
。我是否以错误的方式制作数据?
Edit: If I open the resulting file with a text editor, it looks like this:
编辑:如果我用文本编辑器打开生成的文件,它看起来像这样:
回答by Anne
I wrote a quick example:
Missing: memory management / error handling / proper file handling
我写了一个简单的例子:
缺失:内存管理/错误处理/正确的文件处理
// 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];
You can also add NSImages to the NSMutableArray:
您还可以将 NSImages 添加到 NSMutableArray:
NSString * input = @"/Users/Anne/Desktop/1.png";
NSImage *image = [[NSImage alloc] initWithContentsOfFile: input];
[array addObject:image];
But that will significantly increase the file size.
但这会显着增加文件大小。
回答by Anne
Response to the following comment:
So if I only need to access an image at runtime (in the archive), is there a way to access that image at an index without unarchiving the whole thing? Seems like unnecessary overhead to me.
对以下评论的回应:
因此,如果我只需要在运行时(在存档中)访问一个图像,有没有办法在不取消整个文件的情况下在索引处访问该图像?对我来说似乎是不必要的开销。
I assume you're still struggling with this problem?
Hiding (or encrypting) app resources?
我想你还在为这个问题苦苦挣扎吗?
隐藏(或加密)应用程序资源?
Like i mentioned earlier, combining all files into one big file does the trick.
Just make sure you remember the file-length of each file and file-order.
Then you can extract any specific file you like without reading the whole file.
This might be a more sufficient way if you only need to extract one file at the time.
就像我之前提到的,将所有文件合并成一个大文件就行了。
只要确保记住每个文件的文件长度和文件顺序。
然后您可以提取您喜欢的任何特定文件,而无需阅读整个文件。
如果您一次只需要提取一个文件,这可能是一种更充分的方法。
Quick 'dirty' sample:
快速“脏”示例:
// 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];
Tip:
You can also save the 'index' inside the container file.
For example: The first 500 bytes contain the required information.
When you need a specific file: Read the index, get the file position and extract it.
提示:您还可以将“索引”保存在容器文件中。
例如:前 500 个字节包含所需的信息。
当需要特定文件时:读取索引,获取文件位置并解压。
回答by Guillaume
You are archiving a NSMutable array of NSImage. This two classes conform to the NSCoding protocol required by NSKeyedArchiver, so I don't see where would be your problem.
So, here are many ideas to test.
您正在归档 NSImage 的 NSMutable 数组。这两个类符合 NSKeyedArchiver 要求的 NSCoding 协议,所以我看不出你的问题在哪里。
所以,这里有很多想法需要测试。
First, are you sure that the data you think you have are valid? In your first code snippet, you write [NSData dataWithContentsOfFile:@"0.png"]
. This method expects an absolute file path.
首先,您确定您认为拥有的数据有效吗?在您的第一个代码片段中,您编写[NSData dataWithContentsOfFile:@"0.png"]
. 此方法需要绝对文件路径。
Assuming the problem is not in your code, just in your question, let's continue:
假设问题不在你的代码中,只是在你的问题中,让我们继续:
Do you have something different than nil in the variable data after your archiving? Ie, after the assignement to data, can you add this code. If the assertion fail, you will get an exception at runtime:
归档后的变量数据中是否有与 nil 不同的内容?即,在分配给数据之后,您可以添加此代码。如果断言失败,您将在运行时收到异常:
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:array];
NSAssert(nil != data, @"My object data is nil after archiving");
If the problem was not here, what is the return of the line [data writeToFile:path options:NSDataWritingAtomic error:&error];
(Not the variable error, but the return value of the call to the method - writeToFile: options: error:
)
如果问题不在这里,那行的返回是什么[data writeToFile:path options:NSDataWritingAtomic error:&error];
(不是变量错误,而是调用方法的返回值- writeToFile: options: error:
)
What happens if you simplify your code and just do this:
如果您简化代码并执行以下操作,会发生什么:
result = [NSKeyedArchiver archiveRootObject:data
toFile:archivePath];
If everything was ok, have you tried to unarchive your file with NSKeyedUnarchiver?
如果一切正常,您是否尝试过使用 NSKeyedUnarchiver 解压文件?
回答by Chuck
The problem is that [NSData dataWithContentsOfFile:@"0.png"]
looks for the file "0.png" in the current directory, but what the application thinks of as the current directory is probably not the place you're expecting. For graphical apps, you should always either use an absolute path or a path relative to some place that you can get the absolute path of (e.g. your app bundle, the application support directory, some user-selected location).
问题是[NSData dataWithContentsOfFile:@"0.png"]
在当前目录中查找文件“0.png”,但应用程序认为的当前目录可能不是您期望的位置。对于图形应用程序,您应该始终使用绝对路径或相对于您可以获得绝对路径的某个位置的路径(例如您的应用程序包、应用程序支持目录、某些用户选择的位置)。
For command-line tools, using the current directory is more common. But I doubt that's the case here.
对于命令行工具,使用当前目录更为常见。但我怀疑这里的情况。
回答by FrostyL
Another thing I noticed on Mavericks and up is that the folders in the path must be in existence. Meaning you must create the folder structure prior to saving into that folder. If you try to write to a folder on the desktop or elsewhere, even with sandboxing off, it will fail if the folder does not exist. I know this has been answered already, but I found that my issue continued regardless, but once I make sure that the folder structure was in place, I could do my writing to that folder.
我在 Mavericks 及以上注意到的另一件事是路径中的文件夹必须存在。这意味着您必须在保存到该文件夹之前创建文件夹结构。如果您尝试写入桌面或其他地方的文件夹,即使关闭了沙盒,如果该文件夹不存在,它也会失败。我知道这已经得到了回答,但我发现无论如何我的问题仍然存在,但是一旦我确定文件夹结构到位,我就可以写入该文件夹。
On a side note: I'm sure that you could do this from NSFileManager, and I'll be doing that myself once I finalize my app structure, but hope this helps someone else lost in the sauce.
附带说明:我相信你可以从 NSFileManager 中做到这一点,一旦我完成我的应用程序结构,我就会自己做,但希望这能帮助其他人迷失在酱汁中。