Reputation: 5022
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)
Upvotes: 1
Views: 1145
Reputation: 32104
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 the stringByAppendingPathComponent:
method:
...
NSString *directory = @"/Users/Mikael/Desktop";
NSString *filename = @"MyFile.txt";
NSString *fullPath = [directory stringByAppendingPathComponent:filename];
...
Note that this method will take care of making sure your slashes are well-formed.
Upvotes: 1
Reputation: 299603
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.
Upvotes: 1
Reputation: 14549
NSFileManager * fm = [NSFileManager new];
NSString * dirPath = [fm currentDirectoryPath];
NSString * absPath = [dirPath stringByAppendingPathComponent:@"myfile.file"];
[fm release];
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.
Upvotes: 1