this must be easy but I want to put a file in the Documents folder which is read in at start up. I have the code on how to read and have confirmed its looking in the correct directory. However the file I have ,RootList.txt when saved in the Resources folder in xcode, is stored under the Root.app folder and the Documents folder is empty. Therefore its not finding this file when I start the app.
Is there a way to ensure a file is built into the Documents directory at start up (I'm running this in the simulator).
The alternative is a plist which works fine as well but I'm just curious.
In these situations I follow this approach:
First save your RootList.txt in Resources folder in xCode.You have nothing in your Documents folder, yet.
In the beginning of your applicationDidLaunch call, do:
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *docsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *path = [docsDirectory stringByAppendingPathComponent:#"RootList.txt"];
if(![fileManager fileExistsAtPath:path])
{
NSData *data = [NSData dataWithContentsOfFile:[[[NSBundle mainBundle] resourcePath] stringByAppendingString:#"/RootList.txt"]];
[data writeToFile:path atomically:YES];
}
Now, your file is in Documents folder at startup.
Related
I create a file with attribute NSFileappendonly, i am thinking this is enough to create readonly file in ios.My problem is try to remove the file from device it returns error.Please anyone help me..
A 513 states you do not have permission to write to that folder NSFileWriteNoPermissionError. You need to make sure you are only trying to write to one of the 3 folders in your app's dir (Documents, Temp, or Cache). Generally you use the Documents folder. (Trying to write directly to the main bundle can cause the error you are having)
iOS Environment
You can remove a file with NSFileManager but only if your app is signed and you are attempting to remove from one of the 3 allowed folders. Those 3 folders are only accessible by your app.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [paths objectAtIndex:0];
NSString *yourFile = [documentsDirectoryPath stringByAppendingPathComponent:#"yourFile.txt"];
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtPath:yourFile error:NULL];
I have locally saved one xml file and showing the details by using NSXmlParser(Which is stored in Resource folder). But, now i want to download new xml from url(from client side) and need to store that new xml file in local and also need to delete existing one from the application. How can i do this? Any suggestions? There is any sample code/project for reference? Please help me. Thanks for reading my poor english. Thanks is advance.
although u can delete file from yr resource directory and save new one but the my way is to perform file operation mostly on app diretories like document directory or cache directory.
first u will to save yr xml file from app resource to cache directory then access file from there.And u can also remove file from resource directory ,its no longer needed.
any new file available in internet then first remove old one from cache and add new one to cache directory.
whole thing is as follows:-
//get your cachedirectory path
NSArray *imagepaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cachdirectory = [[NSString alloc] initWithString:[imagepaths objectAtIndex:0]];
//first save your file from resource directory to app's cache directory
NSString * path = [[NSBundle mainBundle] pathForResource:#"fileinresource" ofType:#"xml"];
NSData *filedata = [NSData dataWithContentsOfFile:path];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *savename = [cachdirectory stringByAppendingPathComponent:#"mynewfile.xml"];
[fileManager createFileAtPath:savename contents:filedata attributes:nil];
//remove file from resource directory
[fileManager removeItemAtPath:path error:nil];
//new file from internet is avilable then do following:first remove old file from cache
[fileManager removeItemAtPath:cachdirectory error:nil];
//save new file from internet
NSData *newfiledata=[NSData dataWithContentsOfURL:[NSURL URLWithString:myxmlurlstringpath]];
[fileManager createFileAtPath:savename contents:newfiledata attributes:nil];
I'm not sure that I completely understand how Core Data works on iOS.
I have a large JSON file which I have parsed and imported into core data. This generates an sqlite file. I need this file to be included with the app but every time I delete the app from the device - I have to run the JSON parse script again to create a new sqlite file on the device. I want to be able to exclude the JSON file from the application bundle and dont want to run the parsing script on first use.
How do I go about doing this? Am I doing something wrong?
You will need to create the sqlite file (using your app if you like), then copy it into your project and deploy it with the app. You will also need to add some code to move the file into your documents directory when your app runs for the first time. It can be a simple if file doesn't exist then copy it script.
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *DB = [[paths lastObject] stringByAppendingPathComponent:#"myDB.sqlite"];
if (![fileManager fileExistsAtPath:DB]) {
NSString *shippedDB = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"myDB.sqlite"];
[fileManager copyItemAtPath:shippedDB toPath:DB error:&error];
}
I use this method to ship out pre-built sqlite files, although I haven't used it when CoreData is managing the sqlite file.
I want copy some files to Library or Document in the Product directory,
but when I add a build phase and select Products Directory in destination and input my subdir it's like Library/xxx/.
When I run the App in the simulator, I found nothing in the destination and if I set the destination to Resources, it will be there.
Can you please tell me why this is happening and how I can make it?
The documents directory should only be accessed at runtime. To my knowledge you cannot copy items there during building. What you should do is store those objects that you want in the Documents directory within your bundle and then copy them upon first launch.
Interesting question. I don't know if you can do this as part of the build phase.
To get something into the Documents directory, I have a method that runs at app startup like this:
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:#"filename.txt"];
BOOL success = [fileManager copyItemAtPath:defaultDBPath writablePath error:&error];
That's an incomplete fragment but you probably get the idea. The important thing is the NSDocumentDirectory constant.
Add a new build phase -> New Copy Files Build Phase in Target
I am trying to copy an mp3 file from my Resources folder to a folder inside "Documents" folder of the app. On the simulator this works fine. But when I run it on a device, copying the files gives me this error
Operation could not be completed. (Cocoa error 513.)
The source and destinations paths are fine but I still cannot copy the file. Any ideas? Where can I find out what the cocoa error code 513 means?
Thanks.
Here's the relevant source code
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *folderPath = [documentsDirectory stringByAppendingPathComponent:#"Files"];
NSString *insPath = [NSString stringWithFormat:#"%#.mp3", fileName];
NSString *srcPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:insPath];
NSString *destPath = [folderPath stringByAppendingPathComponent:insPath];
NSLog(#"Src: %#, Dest: %#", srcPath, destPath);
NSError *err;
[fileManager moveItemAtPath:srcPath toPath:destPath error:&err];
NSLog(#"Err desc-%#", [err localizedDescription]);
NSLog(#"Err reason-%#", [err localizedFailureReason]);
Before making a call to moveItemAtPath, I am also creating the directory "Files" and it returns a YES.
Here's the log results
Src: /var/mobile/Applications/512D7565-7EF7-4C13-A015-19EEC3F3B465/MyApp.app/MyFile.mp3, Dest: /var/mobile/Applications/512D7565-7EF7-4C13-A015-19EEC3F3B465/Documents/Files/MyFile.mp3
Err desc-Operation could not be completed. (Cocoa error 513.)
Err reason-(null)
A question
Is there a limit to the file size when copying data from resources to Documents folder? The file I am trying to copy is about 5MB. Could that be a reason?
EDIT:
Just figured out an even simpler solution. Instead of
moveItemAtPath:toPath:error:, just use copyItemAtPath:toPath:error: ... since we truly want to copy the file from the mainBundle and not move it. I should have thought of that sooner!
E.g.
[[NSFileManager defaultManager] copyItemAtPath:mainBundleFilePath
toPath:destPath
error:&err]
See my previous comments below about why this works.
I believe I have the answer to this question. I can say for sure that the issue is not the destination file path.
I was getting the same Cocoa error 513 (NSFileWriteNoPermissionError) with pretty much the exact same code:
[[NSFileManager defaultManager] moveItemAtPath:mainBundleFilePath
toPath:destPath
error:&err]
The problem appears to be that the file, coming from the mainBundle, doesn't have suitable permissions to be moved to another place. I'm not sure if this command, if executed, would actually move the file from the mainBundle or just copy it...but either way, the file manager doesn't seem to like the idea.
The solution is simple: just read the mainBundle file into an NSData object and then write the NSData to a new file. Note the destination file path is the same in both examples, which shows us that lostInTransit is correct in saying that his file path is OK.
For this example, then, the following code will work and not throw an error:
NSData *mainBundleFile = [NSData dataWithContentsOfFile:mainBundleFilePath];
[[NSFileManager defaultManager] createFileAtPath:destPath
contents:mainBundleFile
attributes:nil];
BTW, in my own code, instead of passing a nil for attributes:, I set up an NSDictionary with a NSFileModificationDate attribute. I also wrapped the createFileAtPath:contents:attributes in an error handing if-statement. In other words,
if (![[NSFileManager defaultManager] createFileAtPath:destPath
contents:mainBundleFile
attributes:myAttributes]) {
// handle error as necessary, etc...
}
It took me a while to figure all of this out, so hopefully this solution will be helpful to others.
Are you sure you are getting the path to Documents folder correctly? The absolute path in the simulator is different than the absolute path on the device.
You should use the following to make sure you get the correct path to the Documents directory:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
The path for documentsDirectory on the the device would be something like:
/var/mobile/Applications/30B51836-D2DD-43AA-BCB4-9D4DADFED6A2/Documents
The path on the simulator would be something like:
/Volumes/Stuff/Users/johnDoe/Library/Application Support/iPhone Simulator/User/Applications/118086A0-FAAF-4CD4-9A0F-CD5E8D287270/Documents
You can read more on the File & Networking page on the dev site.
That's the NSFileWriteNoPermissionError:
http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Constants/Reference/reference.html
Somehow, you do have the wrong path and it's not letting you write there. You could also delete the app and try again, in case somehow your app documents directory was set to the wrong permissions...
I'd give us the line of code doing the copy, and print outs of each variable used in that line. Then we can see what the problem is.