I'm trying to use the method seen in the solution here to delete all the files in the iPhone documents directory for the application I'm writing. I've made some minor changes to the code in the solution in order to pass in the string location of the documents directory. My version of the code is the following:
NSString *directory = [[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject] absoluteString];
NSLog(#"%#", directory);
NSError *error = nil;
NSArray *directoryContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:directory error:&error];
if (error == nil) {
for (NSString *path in directoryContents) {
NSString *fullPath = [directory stringByAppendingPathComponent:path];
BOOL removeSuccess = [[NSFileManager defaultManager] removeItemAtPath:fullPath error:&error];
if (!removeSuccess) {
// Error handling
}
}
} else {
// Error handling
NSLog(#"%#", error);
}
When I attempt to run this however, the setting of directoryContents fails due to what's being passed being interpreted as a non-existent directory. Specifically, the two NSLog() statements I have put in the code returns the following:
2013-04-22 11:48:22.628 iphone-ipcamera[389:907] file://localhost/var/mobile/Applications/AB039CDA-412B-435A-90C2-8FBAADFE6B1E/Documents/
2013-04-22 11:48:22.650 iphone-ipcamera[389:907] Error Domain=NSCocoaErrorDomain Code=260 "The operation couldn’t be completed. (Cocoa error 260.)" UserInfo=0x1d5232c0 {NSUnderlyingError=0x1d54c420 "The operation couldn’t be completed. No such file or directory", NSFilePath=file://localhost/var/mobile/Applications/AB039CDA-412B-435A-90C2-8FBAADFE6B1E/Documents/, NSUserStringVariant=(
Folder
)}
As far as I can see the path being printed to the NSLog looks correct so I'm not sure what I'm doing wrong. Can anyone point out to me where my mistake is? Thank you much!
Your code to get the value of directory isn't quite right. You want:
NSURL *directoryURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
NSString *directory = [directoryURL path];
Calling absoluteString on NSURL gives you a file URL. You don't want a file URL, you want the file URL converted to a file path. This is what the path method does.
Another way is:
NSString *directory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
Related
There is a horrible bug which is only occurring intermittently. I'm trying to save data into a sub-folder in 'Application Support' folder. Before saving I will create that sub-folder if not exists
NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES).firstObject;
NSString *packagePath = [cachePath stringByAppendingPathComponent:#"ResourcePackage"];
NSError *error = nil;
BOOL isDirectory = NO;
if(![[NSFileManager defaultManager] fileExistsAtPath:packagePath isDirectory:&isDirectory] || !isDirectory)
{
[[NSFileManager defaultManager] createDirectoryAtPath:packagePath withIntermediateDirectories:YES attributes:nil error:&error];
}
Everything goes fine but except for only one device on which will get error with code 513
Error Domain=NSCocoaErrorDomain Code=513 "您没有将文件“ResourcePackage”存储到文件夹“Application Support”中的权限。" UserInfo={NSFilePath=/var/mobile/Containers/Data/Application/4FF643C4-D568-417F-9A88-5E9FF2326972/Library/Application Support/ResourcePackage, NSUnderlyingError=0x17425e6f0 {Error Domain=NSPOSIXErrorDomain Code=13 "Permission denied"}}
What have I missed or am I doing wrong while writing to this directory?
Thanks!
My app needs to create a subdirectory of the Documents directory. The code below returns the directory URL. First time through it creates the directory, but fails next time because fileExistsAtPath: claims the directory still doesn't exist. I know it exists though because I have set the bundle to make files visible in iTunes and I can see it in iTunes. Any idea what I'm doing wrong?
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
- (NSURL *)applicationSubDirectory
{
NSFileManager *manager = [NSFileManager defaultManager];
NSURL *docDir = [self applicationDocumentsDirectory];
docDir = [docDir URLByAppendingPathComponent:#"Sub" isDirectory:YES];
NSString *docDirPath = [docDir absoluteString];
BOOL isFolder = YES;
if(!([manager fileExistsAtPath:docDirPath isDirectory:&isFolder] && isFolder)) {
NSError *error = nil;
BOOL ret = [manager createDirectoryAtURL:docDir withIntermediateDirectories:NO attributes:nil error:&error];
if(!ret) {
NSLog(#"ERROR app support: %#", error);
abort();
}
}
return docDir;
}
You want to use path instead of absoluteString The former returns the full url absolute path, something like "file:///..." while the latter only returns the file path.
NSString *docDirPath = [docDir path];
So, since you're looking for a file with the path "file:///...." which will never exist, the check always fails. When you go to create the directory, you create it with the URL, so it works.
I'm trying to copy a json file from the application bundle to the Document directory, but surprisingly i'm not able to do that. Here's the code:
NSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [array lastObject];
NSString *path = [docDir stringByAppendingPathExtension:#"themes.json"];
if (![[NSFileManager defaultManager] fileExistsAtPath:path])
{
NSString *themesPath = [[NSBundle mainBundle] pathForResource:#"themes" ofType:#"json"];
NSError *error = nil;
[[NSFileManager defaultManager] copyItemAtPath:themesPath toPath:path error:&error];
if (error)
NSLog(#"Error %#", error);
}
It produces the following error:
Error Domain=NSCocoaErrorDomain Code=513 "The operation couldn’t be completed. (Cocoa error 513.)" UserInfo=0x194a0e90 {NSSourceFilePathErrorKey=/var/mobile/Applications/ACED3EF9-B0D8-49E8-91DE-37128357E509/Frinder.app/themes.json, NSUserStringVariant=(
Copy
), NSFilePath=/var/mobile/Applications/ACED3EF9-B0D8-49E8-91DE-37128357E509/Frinder.app/themes.json, NSDestinationFilePath=/var/mobile/Applications/ACED3EF9-B0D8-49E8-91DE-37128357E509/Documents.themes.json, NSUnderlyingError=0x194a0400 "The operation couldn’t be completed. Operation not permitted"}
After a search i've found this question and tried to modify my code as follows:
if (![[NSFileManager defaultManager] fileExistsAtPath:path])
{
NSString *themesPath = [[NSBundle mainBundle] pathForResource:#"themes" ofType:#"json"];
NSData *data = [NSData dataWithContentsOfFile:themesPath];
BOOL success = [[NSFileManager defaultManager] createFileAtPath:path contents:data attributes:nil];
if (!success)
NSLog(#"Fail");
}
but it doesn't work either. success variable is NO. The last thing i tried was:
[data writeToFile:path atomically:YES];
but still in vain. it returns NO.
I need to note that the issue arises on a device only. On a simulator it works all right.
Can anybody give me a clue?
The first example is correct on one thing:
[docDir stringByAppendingPathExtension:#"themes.json"];
should be:
[docDir stringByAppendingPathComponent:#"themes.json"];
This becomes clear we you read the error message, you see that it tries to write the file to /var/mobile/Applications/ACED3EF9-B0D8-49E8-91DE-37128357E509/Documents.themes.json. Notice that there a . where there should be a /.
The stringByAppendingPathExtension: is used for adding a extension to a file, jpg, txt, html,.....
stringByAppendingPathComponent will add a file to a path, by adding the correct directory separator, you case /.
You second example will definitely fail since the app bundle is readonly.
I try to get my file in my self created Directory in the Documents Directory into a NSData Object like this:
NSString *path = [documentsDirectory stringByAppendingFormat:#"%#%#",#"/",fileName];
NSError* errorr = nil;
NSData *fileData = [NSData dataWithContentsOfFile:path options: 0 error: &errorr];
if (fileData == nil)
{
NSLog(#"Failed to read file, error %#", errorr);
}
else
{
}
But i always get this error:
Failed to read file, error Error Domain=NSCocoaErrorDomain Code=257 "The operation couldn’t be completed. (Cocoa error 257.)" UserInfo=0x156be110 {NSFilePath=/var/mobile/Applications/679253E3-652C-45EE-B589-609E52E4E3B0/Documents/upload/test.xml, NSUnderlyingError=0x156ba7f0 "The operation couldn’t be completed. Permission denied"}
So if i check if the file is readable:
if ([[NSFileManager defaultManager] isReadableFileAtPath: path] == YES)
NSLog (#"File is readable");
else
NSLog (#"File is read only");
i get the result that the file is readable, so why do i get the error if i want to parse that file into NSData?!
UPDATE: i created my file like this:
NSString *filePath = [self dataFilePath:fileName];
[xmlData writeToFile:filePath atomically:YES];
- (NSString *)dataFilePath: (NSString *) path {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"upload"];
NSError *error = nil;
if (![[NSFileManager defaultManager] fileExistsAtPath:documentsDirectory])
[[NSFileManager defaultManager] createDirectoryAtPath:documentsDirectory withIntermediateDirectories:NO attributes:nil error:&error];
NSString *documentsPath = [documentsDirectory
stringByAppendingPathComponent:path];
return documentsPath;
}
UPDATE2: After creating the file, i move it into another Directory with this function:
- (void)moveXmlFilesToUploadDirectory
{
#try {
//Check if FILES_DIR exists
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:FILES_DIR];//filesDir
NSString *uploadDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:UPLOAD_DIR];//filesDir
if ([[NSFileManager defaultManager] fileExistsAtPath:documentsDirectory])
{
NSString *extension = #"xml";
NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectory error:NULL];
NSEnumerator *e = [contents objectEnumerator];
NSString *filename;
while ((filename = [e nextObject])) {
if ([[filename pathExtension] isEqualToString:extension]) {
[[NSFileManager defaultManager] moveItemAtPath:documentsDirectory toPath:[uploadDirectory stringByAppendingPathComponent:filename] error:NULL];
}
}
}
}
#catch (NSException *exception) {
}
#finally {
}
}
Maybe the Problem is after moving the file! Cause if i try to get my file into a NSData before i move it, everything works...
It seems that you try to copy the whole directory to a destination meant to be a file. The result is that the filepath is a directory path in the end so you can't open it like a file which leads to the permission error message.
You should update your copy code to
while ((filename = [e nextObject])) {
if ([[filename pathExtension] isEqualToString:extension]) {
[[NSFileManager defaultManager] moveItemAtPath:[documentsDirectory stringByAppendingPathComponent: filename] toPath:[uploadDirectory stringByAppendingPathComponent:filename] error:NULL];
}
}
to copy every file individually. That will create than the actual file at the destination path intend of a directory.
The chances are high that you don't have the right permissions for that file. Please check the permissions and add read access for the current user or "everyone". You can set the read permissions for your user by the info dialog (cmd + i) or in the terminal with chmod u+r test.xml. Eventually you have to set the owner before with
sudo chown yourusername test.xml
Hope that makes sense.
I want to write a file in the Documents folder of my iPhone app.
But when I try to open the path I get the
Cocoa error 257 - Permission Denied.
Here's a little code snippet:
// create path to file
NSURL *path = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] objectAtIndex:0];
NSLog(#"%#", [path description]);
NSError *error = nil;
NSString *filename = [NSString stringWithContentsOfURL:path encoding:NSUTF8StringEncoding error:&error];
NSLog(#"%#", error);
NSLog(#"%#", [filename description]);
Can you tell me please, what's wrong with that code?
Thanks!
It looks as though you're trying to open the documents directory rather than a file in that directory. stringWithContentsOfURL loads the contents of the file into the NSString, so it's not a filename.
If filename should be a path rather than the contents of a file, use stringWithContentsOfURL: instead.