I've been writing this app for iPhone and I need to use sqlite. I have pre-loaded my sqlite with a bunch of data, I copied that sqlite file into my project folder. And when I launch the app, it seems like the sqlite data file was not copied to the simulator's app file (the document place). Here's my code:
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSString *dbPath = [documentsDir stringByAppendingPathComponent:#"moviedbl.data"];
BOOL success = [fileManager fileExistsAtPath:dbPath];
if(!success){
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent: #"moviedbl.data"];
//NSString *defaultDBPath = [[NSBundle mainBundle] pathForResource:#"moviedbl" ofType: #"data"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];
if(!success){
NSAssert1(0, #"Failed to create writable database file with message '%'.", [error localizedDescription]);
}
}
It seems that defaultDBPath refers to the app folder in the simulator, which originally does not contain any sqlite file, and instead, is actually waiting for a sqlite file to be copied to it. From what I understand, to copy the file, we should get the file from our bundle (not sure if bundle refers to our project folder or what, but I assumed it is our project folder) and copy it to our simulator. I've been stuck on this for days, please enlighten me... Thankyou very much in advance!!!
UPDATE:
So I actually got it working after all. At first I thought it was because I didn't copy the files from mainBundle or something, but it turns out that I did when I opened the actual folder of the .app in the path. I saw that the database it actually included. Something weird is that it doesn't have a file type, but in xCode it shows the file type as "data", so I kept using ofType: #"data". So in the end I changed it to ofType: #"" and it worked! Anyways! stupid me, but thanks for everyone who tried to help!! :D
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSString *dbPath = [documentsDir stringByAppendingPathComponent:#"moviedbl.data"];
if([fileManager fileExistsAtPath:dbPath]==NO){
NSString *defaultDBPath = [[NSBundle mainBundle] pathForResource:#"moviedbl" ofType: #"data"];
BOOL success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];
if(!success){
NSAssert1(0, #"Failed to create writable database file with message '%'.", [error localizedDescription]);
}
}
Related
I am new programmer in objective c. I want to create "Download" directory inside the i phone(path : setting (i phone setting directory))I want to know is it possible?. I am using i phone simulator to test the program.
Another question is, How can I access created directory in i phone simulator. Below contains code I tried to create folder in i phone. But I can not access that directory by using i phone simulator. what the wrong of this code?
NSString *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:#"/Test"];
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
[[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error];
you can create Directory in to Document Directory as sub Folder like this way:-
-(IBAction)CreatDirInDocDir
{
NSFileManager *filemgr = [NSFileManager defaultManager];
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *dir = [NSString stringWithFormat:#"%#",DirName];
NSString *path = [documentsDirectory stringByAppendingPathComponent:dir];
NSError *error;
if ([filemgr fileExistsAtPath:path ] == YES){
}
else
{
NSLog (#"File not found");
[[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:NO attributes:nil error:&error];
}
}
when ever you create directory in to Document directory folder then you can get all list of Created Custom directory like this way:-
//Get all Directory
NSFileManager *fileMan = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSArray *filePathsArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:documentsDirectory error:nil];
NSLog(#"files array %#", filePathsArray);
NSMutableArray *directoryList=[[NSMutableArray alloc]init];
for ( NSString *direPath in filePathsArray )
{
NSString *path = [documentsDirectory stringByAppendingPathComponent:direPath];
BOOL isDir = NO;
[fileMan fileExistsAtPath:path isDirectory:(&isDir)];
if(isDir) {
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:path];
NSLog(#"log path ==%#",fullPath);
[directoryList addObject:fullPath];
}
}
NSLog(#"list path ==%#",directoryList);
Now you have array of all directory you can get any directory with index :)
Hope its helps you
All The method posted here are correct and there are tons of answers about them, but I'd like to warn you about a concept. Since The introduction of iCloud, Apple started to reject applications that saves a lot of data in document directory, when they are used by means of caches or they could be downloaded again later. The problem here is that you can backup your ios devices on the cloud and document directory is one of the backupped. Can you image yourself backupping one GB on application on the cloud? That's the explanation about apple rejects. To avoid that temp/redownloadable/cached data should be saved in cache directory. This useful dir is freed when the device is running out of space on "disk", like when you try to install a new app and you don't have enough space. So this is ok if your data can be downloaded again and are not indispensable. the other way around is to keep data in the document directory but telling the system to do not backup them, this is possible adding a special flag to the doc subdirectory where you saved the file, here is how link , pay attention that this methods is only available from 5.0.1 so you need to check its existence if you target lower ioses. In this case the system will not free your data and not backup them this is safe for apple guidelines. hope this helps
For creating directory you can use:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:#"Test"];
NSError *error;
if (![[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error])
{
NSLog(#"Couldn't create directory error: %#", error);
}
For getting the files inside that directory you can use:
NSArray *datArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:dataPath error:&error];
if(error)
{
NSLog(#"Could not get list from directory, error = %#",error);
}
Here all file names will be in the datArray.
No need append '/' . Just Use
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:#"Test"];
Try This
NSArray *dirPath;
NSString *docsDir;
NSFileManager *filemgr = [NSFileManager defaultManager];
dirPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPath objectAtIndex:0];
if ([filemgr changeCurrentDirectoryPath: docsDir] == NO)
{
NSLog(#"Error");
}else {
NSString *currentPath = [filemgr currentDirectoryPath];
NSLog(#"%#",currentPath);
}
NSString *dataDirectory = [docsDir stringByAppendingPathComponent:#"Test"];
if ([filemgr fileExistsAtPath:dataDirectory]){
NSLog(#"dir Exist");
}else{
NSLog(#"Creating Dir");
[filemgr createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error];
}
Anyone want to show your created directory in i phone simulator follow bellow steps :
Go to finder
Click Command +Shift + g
Type ~/Library then click Go
Open Application Support --> i phone simulator
Then you can find your created applications and directories..
I am trying to create a plist file that I will write to later in my app. In the first viewDidLoad I call the following method
-(void)createFavoritesFile{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *documentDBFolderPath = [documentsDirectory stringByAppendingPathComponent:#"data.plist"];
if (![fileManager fileExistsAtPath:documentDBFolderPath])
{
NSLog(#"file doesnt exist");
NSString *resourceDBFolderPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"data.plist"];
[fileManager copyItemAtPath:resourceDBFolderPath toPath:documentDBFolderPath error:&error];
}
else{
NSLog(#"file exists");
}
}
However every time I run the app, I cannot find a file created, and if I close the app and reopen, NSLog shows that file doesnt exist again. Am I missing something?
You're ignoring the return value and error from -copyItemAtPath:toPath:error:. I'm willing to bet that call is returning NO and populating some error. You should check the return value of that and print out the error if it returns NO.
One possible reason why this is failing is you might not actually have a Documents folder yet, for some reason. You can ask NSFileManager to create it for you.
Print your resource path and see if the file exists in there. If so, but not working check this question: Working with paths from [[NSBundle mainBundle] resourcePath]
Anyway, if your resource is in your main bundle you can always use:
- (NSString *)pathForResource:(NSString *)name ofType:(NSString *)extension
I want to read/write to cache.plist
If I want to read an existing premade plist file stored in the resources folder I can go:
path = [[NSBundle mainBundle] bundlePath];
NSString *finalPath = [path stringByAppendingPathWithComponent#"cache.plist"];
NSMutableDictionary *root = ...
But then I wish to read it from the iPhone.
Can't, the Resources folder is only readable.
So I need to use:
NSDocumentDirectory, NSUserDomain,YES
So how can I have my plist file preinstalled to the Document Directory location?
Thus meaning I don't have to mess around with untidy code copying the plist file over at startup. (Unless that's the only way).
I know this isn't really what you're after, but as far as I know the only way to get the document into the Documents folder IS to actually copy it there...but only on the first startup. I'm going something similar for a sqlite database. Code is below, it works but please note it could do with a little bit of cleaning up:
// Creates a writable copy of the bundled default database in the application Documents directory.
- (void)createEditableCopyOfDatabaseIfNeeded {
// First, test for existence.
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:#"WordsDatabase.sqlite3"];
createdDatabaseOk = [fileManager fileExistsAtPath:writableDBPath];
if (createdDatabaseOk) return;
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"WordsDatabase.sqlite3"];
createdDatabaseOk = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
}
Just call in your AppDelegate - not too messy really?
Easy. Look first to see if it's in the documents directory. If it's not, find it inside your app's Resources folder ([[NSBundle mainBundle] pathForResource...]), then copy it into the documents directory using [[NSFileManager defaultManager] copyItemAtPath:...]. Then use the fresh copy in the documents directory with impunity.
The final product
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *finalPath = [path stringByAppendingPathComponent:#"Cache.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *giveCachePath = [documentsDirectory stringByAppendingPathComponent:#"Cache.plist"];
BOOL fileExists = [fileManager fileExistsAtPath:giveCachePath];
if (fileExists) {
NSLog(#"file Exists");
}
else {
NSLog(#"Copying the file over");
fileExists = [fileManager copyItemAtPath:finalPath toPath:giveCachePath error:&error];
}
NSLog(#"Confirming Copy:");
BOOL filecopied = [fileManager fileExistsAtPath:giveCachePath];
if (filecopied) {
NSLog(#"Give Cache Plist File ready.");
}
else {
NSLog(#"Cache plist not working.");
}
i use sqlite database on my iphone app and
i need to update this database from the internet from my server
how i can download the new database and delete the old database
and recopy the new database to document directory
Download your file with +[NSData dataWithContentsOfURL:].
Close sqlite DB, if opened.
Remove old DB file (may be just rename - if something went wrong with downloaded data, you may revert to prev. version of a DB faile) with -[NSFileManeger removeItemAtPath:error:]
Write downloaded data to a DB file with -[NSData writeToFile:atomically:].
Here is the full code
//replacing the db that I have emailed from app.
-(void)handleOpenURL:(NSURL *)url
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *txtPath = [documentsDirectory stringByAppendingPathComponent:#"/DemoApp.sqlite"];
NSURL *newUrl = [[NSURL alloc] initWithString:
[txtPath stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
if ([fileManager fileExistsAtPath:txtPath] == NO) {
[fileManager copyItemAtURL:url toURL:newUrl error:&error];
}
else if ([fileManager fileExistsAtPath:txtPath] == YES) {
[fileManager removeItemAtPath:txtPath error:&error];
[fileManager copyItemAtURL:url toURL:newUrl error:&error];
}
}
Hope this helps
I want to initialize my app with a small sqlite3 DB. I tried to put it in the Documents directory, but sometimes it copies it with zero size and sometimes it doesnot copy it at at all.
How sholud I initialize my app with a DB full of info?
Thankyou
How do you copy it with your application?
If you ship your application with DB inside app bundle (as a resource) you should copy it to the documents folder from resources if it is absent and work with it there:
NSFileManager *fileManager = [[NSFileManager defaultManager] autorelease];
BOOL exists = [fileManager fileExistsAtPath:databasePath];
if (exists) {
return;
}
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseName];
[fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
Thank you Vladimir,
This was helpful. I made a few changes and here is the final result that works great:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *databasePath = #"personalLMS.s3db";
NSFileManager *fileManager = [[NSFileManager defaultManager] autorelease];
NSString * databasePathFromApp = [[NSBundle mainBundle] pathForResource:#"personalLMS" ofType:#"s3db"];
[fileManager copyItemAtPath:databasePathFromApp toPath:[documentsDirectory stringByAppendingPathComponent:databasePath] error:nil];