将 NSString 写入相关文件
将 NSString 和 NSData 对象写入相对文件路径时出现奇怪的行为。这是一个例子:
NSString *string = @"I am a file!";
NSError *error = nil;
NSString *fileName = @"text.txt";
BOOL written = [string writeToFile:fileName atomically:YES encoding:NSUTF8StringEncoding error:&error];
if (written) {
NSLog(@"Successfully written to file.");
} else {
NSLog(@"Error: %@", [error localizedDescription]);
}
当我运行这个时,我总是得到“成功写入文件。”,但该文件永远不存在。不知怎的,程序认为它是成功的并且没有生成错误。
我做错了什么? (我使用的是 Mac OS X Lion)
I'm getting strange behavior writing NSString and NSData objects to relative file paths. Here's an example:
NSString *string = @"I am a file!";
NSError *error = nil;
NSString *fileName = @"text.txt";
BOOL written = [string writeToFile:fileName atomically:YES encoding:NSUTF8StringEncoding error:&error];
if (written) {
NSLog(@"Successfully written to file.");
} else {
NSLog(@"Error: %@", [error localizedDescription]);
}
When I run this I always get "Successfully written to file.", but the file is never there. Somehow the program thinks it was successful and no error is generated.
What am I doing wrong? (I'm on Mac OS X Lion)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这将写入当前目录。当您在 Xcode 4 下运行某些内容时,默认的当前目录将是
~/Library/Developer/Xcode/DerivedData//Build/Products/
。您可以使用方案覆盖它。当您从命令行运行程序时,当前目录就是您运行该程序时的当前目录。如果您使用 Finder 启动应用程序,则当前目录通常为/
。原则上写当前工作目录就可以了。在命令行应用程序中执行此操作很常见。因此,关于 @craig 关于 writeToFile: 期望绝对路径的评论,我认为这不是真的。它期望并写入路径。它不在乎它是绝对的还是相对的。这是一个基础类,在命令行程序中与 GUI 一样有用。
但在 GUI 应用程序中,您应该避免相对路径。原则上,您可以设置当前目录,然后写入文件,但这在大型程序中通常是一个坏主意,因为它不是线程安全的(整个程序只有一个 cwd)。而且 GUI 应用程序往往有一些不可预测的当前目录,因此它不会带来良好的用户体验。
但对于为什么没有收到错误的问题,那是因为它可能已经成功写入了。你只是不知道该去哪里寻找。
This writes to the current directory. The default current directory when you run something under Xcode 4 is going to be
~/Library/Developer/Xcode/DerivedData/<prodDir>/Build/Products/<configuration>
. You can override this using a Scheme. When you run a program from the commandline, then the current directory is whatever the current directory was when you ran the program. If you use Finder to launch the app, then the current directory will often be/
.In principle, it's fine to write the current working directory. It's very common to do this in command-line apps. So regarding @craig's comment about
writeToFile:
expecting an absolute path, I don't think that's really true. It expects and writes to a path. It doesn't care if it's absolute or relative. This is a Foundation class, and is just as useful in a command-line program as a GUI.But in a GUI app, you should avoid relative paths. In principle, you could set the current directory and then write the file, but this is usually a bad idea in a large program since it's not thread safe (there is only one cwd for the whole program). And GUI apps tend to have somewhat unpredictable current directories, so it doesn't make for a good user experience.
But to the question of why you didn't get an error, it's because it probably successfully wrote it. You just didn't know where to look.
请记住,currentDirectoryPath 反映了您的程序工作目录,直到您使用
-changeCurrentDirectoryPath:
更改它为止,程序工作目录可能会有所不同,具体取决于其启动方式,并且不能依赖。keep in mind that currentDirectoryPath reflects your programs working directory until you change it with
-changeCurrentDirectoryPath:
, the programs working directory can be different depending on how it was launched, and can't be relied upon.writeToFile: 方法的第一个参数(在您的示例中)是相对路径,但您可能希望使用绝对路径。否则,系统将相对于当前可执行文件放置您的文件。当您在 Xcode 中运行时,这可能不是您期望的结果。 (正如 Rob 在他的回答中提到的,这个位置有些隐藏,并且可以根据您使用的 Xcode 版本而改变。)
如果您想使用
NSString
对象构建目录路径,我会推荐stringByAppendingPathComponent:
方法:请注意,此方法将负责确保斜杠格式正确。
The first parameter to the
writeToFile:
method (in your example) is a relative path, but you probably want to use an absolute path. Otherwise, the system will place your files relative to the current executable. When you're running inside Xcode, this might not be where you expect them to end up. (As Rob mentioned in his answer, this location is somewhat buried, and can change depending on which version of Xcode you're using.)If you want to build up a directory path using
NSString
objects, I would recommend thestringByAppendingPathComponent:
method:Note that this method will take care of making sure your slashes are well-formed.