问题
I looked here and there but to no avail.
Consider:
- (void) write: (NSString *) xId data:(NSData *) data forClass: (Class) c {
NSFileManager * fm = [NSFileManager defaultManager] ;
NSString * instancePath = [self instancePath:xId forClass: c] ;
errno = 0 ;
BOOL success = [fm createFileAtPath: instancePath
contents: data
attributes: nil] ;
if (!success) {
::NSLog(@"Couldn't write to path: %@", instancePath) ;
::NSLog(@"Error was code: %d - message: %s", errno, strerror(errno));
} else {
::NSLog(@"COULD write to path: %@", instancePath) ;
::NSLog(@"Error was code: %d - message: %s", errno, strerror(errno));
}
}
Which then prints:
2013-03-22 18:59:27.177 otest[18490:303] COULD write to path: /Users/verec/Library/Application Support/iPhone Simulator/6.1/Documents/cal/ModelRepo/ModelRepo#0.sexp
2013-03-22 18:59:27.177 otest[18490:303] Error was code: 3 - message: No such process
2013-03-22 18:59:27.178 otest[18490:303] Couldn't write to path: /Users/verec/Library/Application Support/iPhone Simulator/6.1/Documents/cal/ModelContainer/20130322.sexp
2013-03-22 18:59:27.178 otest[18490:303] Error was code: 3 - message: No such process
- Why is it that errno is not 0 even though `success' is YES in the first case (the "COULD" case)
- Can anyone spot the difference in the actual path that makes success=YES in the first ("COULD") case but success=NO in the second ("Couldn't")?
This is while running a OCUnit test, Xcode 4.6.1 Simulator running iOS 6.1
I'm just puzzled :-(
回答1:
The
errno
variable is generally only set by system calls (and some library functions) if the call failed. It is not modified if a system call succeeded, and may contain a non-zero value from a previous error.One should print or save
errno
immediately after a failed system call. In your case,NSLog(@"Couldn't write to path: %@", instancePath);
actually modifies errno. ("No such process" is very unlikely to be the correct failure reason.)
- For the same reason, you cannot assume that
errno
contains the correct value aftercreateFileAtPath
failed. It actually did in my test, but it is not documented that this method sets/preserveserrno
correctly.
回答2:
I'm writing this answer to address verec's error code in more detail with a code blob. He actually alluded to this in his comment on the accepted answer.
The error he got from createFileAtPath
was 3 (ESRCH) - No Such Process
One reason this might be the case is that createFileAtPath
will NOT create intermediate directories, so if a directory on the way to the path you want to create doesn't exist, it will fail with this error code.
Instead you have to use createDirectoryAtPath:withIntermediateDirectories:attributes:error:
to first create the directories and then use createFileAtPath
after successfully creating those.
NSString *fileParentFolderPath;
NSString *filePath;
//first create the directory, createFileAtPath can't create intermediate dirs
NSError *error;
if([[NSFileManager defaultManager] createDirectoryAtPath:fileParentFolderPath
withIntermediateDirectories:YES attributes:nil error:&error]) {
//then create the file
if(![[NSFileManager defaultManager] createFileAtPath:filePath
contents:nil attributes:nil]) {
NSLog(@"Faliure creating File error was code: %d - message: %s", errno, strerror(errno));
};
} else {
NSLog(@"Faliure creating dir w error: %@", error);
};
来源:https://stackoverflow.com/questions/15578179/createfileatpath-ocunit-errno-blues