how to create a sqlite file when the application starts (didFinishLaunchingWithOptions) the test if it already or not exsist otherwise create the file sqlite
Like this... the sqlPath variable is the path to the pre-made sql database on your ressource
- (void) checkAndCreateSQL
{
if (![[NSFileManager defaultManager] fileExistsAtPath:[documentPath stringByAppendingString:#"/database.sql"]]) {
[[NSFileManager defaultManager] createFileAtPath:[documentPath stringByAppendingString:#"/database.sql"]
contents:[NSData dataWithContentsOfFile:sqlPath]
attributes:nil];
}
}
EDIT 1:
You can create the database on your mac using this command line :
sqlite3 database.sql < DATABASE_CREATION.txt
in the DATABASE_CREATION.txt something like this :
CREATE TABLE IF NOT EXISTS `group` (
`id` integer PRIMARY KEY,
`name` text,
`position` integer
);
Then put directly the database.sql file into your project resource. (like an image)
You'd probably want to use the default Core Data libraries instead of manually creating and handling a single sqlite file. Please check the official Apple Core Data Programming Guide. It will automatically handle the creation and update of the inner database in the app.
sqlite3 *reference2Database() {
if (_database == nil) {
// First, test for existence.
NSError *error;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:#"my.sqlite"];
if ([fileManager fileExistsAtPath:writableDBPath] == NO) {
// Database file doesnt exists. Copy the database at writable path (documents directory).
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"my.sqlite"];
[fileManager removeItemAtPath:writableDBPath error:nil];
BOOL databaseCopied = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
if (!databaseCopied) {
// Handle the error...
}
}else {
// Open the database. The database was prepared outside the application.
if (sqlite3_open([writableDBPath UTF8String], &_database) != SQLITE_OK) {
// Even though the open failed, call close to properly clean up resources.
sqlite3_close(_database);
_database = nil;
// Additional error handling, as appropriate...
}
}
}
return _database;
}
// Sample usage.
-(void) someDatabaseFunction {
sqlite3 *database = reference2Database();
// Do something with "database"...
}
// Close the database. This should be called when the application terminates.
void closeDatabase() {
if (_database == nil) return;
// Close the database.
if (sqlite3_close(_database) != SQLITE_OK) {
// Handle the error...
}
_database = nil;
}
NOTE: At the top of the file, you should have: static sqlite3 *_database = nil;
I use Matteo Bertozzi's SQLite Wrapper to create my sqlite database with the following code:
-(void)checkDatabase
{
if([[NSFileManager defaultManager] fileExistsAtPath:DBPATH] == NO)
{
sqlite = [[Sqlite alloc] init];
if (![sqlite open:DBPATH]) return;
[sqlite executeNonQuery:#"DROP TABLE yourtable"];
[sqlite executeNonQuery:#"CREATE TABLE yourtable (record1 TEXT NOT NULL,
record2 TEXT NOT NULL,
record3 TEXT NOT NULL,
record4 TEXT NOT NULL);"];
NSArray *results = [sqlite executeQuery:#"SELECT * FROM yourtable;"];
for (NSDictionary *dictionary in results) {
for (NSString *key in [dictionary keyEnumerator])
NSLog(#" - %# %#", key, [dictionary objectForKey:key]);
}
[results release];
[sqlite release];
}
}
Related
I am working on storing a list of audio files into my document directory and then fetching them.
It gives me a list of audio files along with this it gives me a file with name #".DS_Store". While fetching content I want to leave this file of documents directory.
Is there any way I can get rid of this while fetching the audio list other than removing this from array or apply a #".DS_Store" check.
What exactly is the reason for this.?
#pragma mark - Saving Audio in Document Directory
-(void)saveAudioinDocumentDirectory:(ASIHTTPRequest *)theRequest
{
/*save the Audio file in Document Directory */
NSFileManager *fileManager=[NSFileManager defaultManager];
NSLog(#"GOT THE SIZe OF AUDIO %d",[[theRequest responseData] length]);
NSLog(#"AUDIO ID IS %#",[[theRequest userInfo] valueForKey:#"audioIndex"]);
/*Get the Path to Application Documents Directory*/
NSArray *docDir=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
/*append the neccessary file extension */
NSString *filepathStr=[NSString stringWithFormat:#"/%#/%#.mp3",docDir,[NSString stringWithFormat:#"%#",[[theRequest userInfo] valueForKey:#"audioIndex"]]];
/*Check if my crrent file exists in the Documents Directory*/
if(![fileManager fileExistsAtPath:filepathStr])
{
/* file doesnt exists */
/*create a NSdata of File*/
NSData *data=[NSData dataWithData:[theRequest responseData]];
NSLog(#"%#",filepathStr);
if ([data length] >0 ){
/*write the File at the Location in Documents Directory */
[data writeToFile:filepathStr atomically:YES];
NSLog(#"Successfully saved the file to %#", filepathStr);
}
else if([data length] == 0)
{
NSLog(#"Nothing was downloaded.");
}
}
/*After saving fetch the path til documents Directory*/
NSArray *folders = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
/*Get the Path for Files */
NSString *s=[folders objectAtIndex:0];
/*Fetch the list of Files stored in Documents Directory*/
NSArray *contents = [fileManager contentsOfDirectoryAtPath:s error:NULL];
NSLog(#"TOTAL NUMBER OF AUDIO FILES %d %#",[contents count],[contents objectAtIndex:0]);
if([Audiolistforstr isEqualToString:#"AudioListForIntro"])
{
// NSLog(#"Audiolistforstr#"IntroThirdRow" in reading audio from document Intro IS %#",Audiolistforstr);
/*Intro*/
[AudioListArrForIntro removeAllObjects];
[AudioListArrForIntro addObjectsFromArray:contents];
if([AudioListArrForIntro containsObject:#".DS_Store"])
{
[AudioListArrForIntro removeObject:#".DS_Store"];
}
NSLog(#"FINAL LIST %#",AudioListArrForIntro);
}
else if([Audiolistforstr isEqualToString:#"AudioListForCredits"])
{
// NSLog(#"Audiolistforstr#"IntroThirdRow" in reading audio from document credit IS %#",Audiolistforstr);
/*credits*/
[AudioListArrForCredits removeAllObjects];
[AudioListArrForCredits addObjectsFromArray:contents];
if([AudioListArrForCredits containsObject:#".DS_Store"])
{
[AudioListArrForCredits removeObject:#".DS_Store"];
}
NSLog(#"FINAL LIST %#",AudioListArrForCredits);
}
/* Did we find anything? */
if([Audiolistforstr isEqualToString:#"AudioListForIntro"])
{
// NSLog(#"Audiolistforstr#"IntroThirdRow" in reading audio fromRELOADNG TABLE Intro IS %#",Audiolistforstr);
/*Intro*/
if ([AudioListArrForIntro count] == 0)
{
}
else
{
UIView *vw=(UIView *)[self.view viewWithTag:ViewAddAudioIntroTag];
[(UITableView *)[vw viewWithTag:tblIntroAudioListTag] reloadData];
}
}
else if([Audiolistforstr isEqualToString:#"AudioListForCredits"])
{
// NSLog(#"Audiolistforstr#"IntroThirdRow" in reading audio fromRELOADNG TABLE Intro IS %#",Audiolistforstr);
/*Credits*/
if ([AudioListArrForCredits count] == 0)
{
}
else
{
/*AudioListForCredits*/
UIView *vw=(UIView *)[self.view viewWithTag:ViewAddAudioCreditsTag];
[(UITableView *)[vw viewWithTag:tblCreditsAudioListTag] reloadData];
}
}
}
Any help would be appreciated.
Thanks
Vikas
You can check for .DS_Store after NSArray *docDir=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; line........that is,
NSMutableArray * dirContents = [[NSMutableArray alloc] initWithArray:docDir];
if([docDir containsObject:#".DS_Store"])
{
[dirContents removeObject:#".DS_Store"];
}
By this, dirContents removes the entry of .DS_Store.
Filter your document directory contents. For example, if you are having audio files with extension of .mp3, then you can get all the mp3 files as below:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSArray *directoryContent = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectory error:NULL];
directoryContent = [directoryContent filteredArrayUsingPredicate:
[NSPredicate predicateWithFormat:#"pathExtension ==[c] %#", #"mp3"]];
This will omit all other files than the mp3 files..
All the best!!!
The API you're using:
NSArray *contents = [fileManager contentsOfDirectoryAtPath:s error:NULL];
returns all files found at the path, which would include the ".DS_Store" file.
I'd recommend assigning "contents" to a mutable array, e.g.:
NSMutableArray * contents =
[[NSMutableArray alloc] initWithArray: [fileManager contentsOfDirectoryAtPath:s error:NULL]];`
and iterate through the array to find and removing any and all files that don't have ".mp3" as a path extension.
I'd also recommend not starting any variable with an upper case letter (e.g. instead of "Audiolistforstr", use "audiolistforstr" or even better, "arrayofAudioFiles"). Objective C best practice is to start all variables and methods with lower case letters.
Its Working well..
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSFileManager *manager = [NSFileManager defaultManager];
NSArray *imageFilenames = [manager contentsOfDirectoryAtPath:documentsDirectory error:nil];
for (int i = 0; i < [imageFilenames count]; i++)
{
NSString *imageName = [NSString stringWithFormat:#"%#/%#",documentsDirectory,[imageFilenames objectAtIndex:i] ];
if (![[imageFilenames objectAtIndex:i]isEqualToString:#".DS_Store"])
{
UIImage *myimage = [UIImage imageWithContentsOfFile:imageName];
UIImageView *imageView = [[UIImageView alloc] initWithImage:_myimage];
}
}
I'm getting my data ,with several similar methods, from sqlite3 file like in following code:
-(NSMutableArray *) getCountersByID:(NSString *) championID{
NSMutableArray *arrayOfCounters;
arrayOfCounters = [[NSMutableArray alloc] init];
#try {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *databasePath = [[[NSBundle mainBundle] resourcePath ]stringByAppendingPathComponent:#"DatabaseCounters.sqlite"];
BOOL success = [fileManager fileExistsAtPath:databasePath];
if (!success) {
NSLog(#"cannot connect to Database! at filepath %#",databasePath);
}
else{
NSLog (#"SUCCESS getCountersByID!!");
}
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK){
NSString *tempString = [NSString stringWithFormat:#"SELECT COUNTER_ID FROM COUNTERS WHERE CHAMPION_ID = %#",championID];
const char *sql = [tempString cStringUsingEncoding:NSASCIIStringEncoding];
sqlite3_stmt *sqlStatement;
int ret = sqlite3_prepare(database, sql, -1, &sqlStatement, NULL);
if (ret != SQLITE_OK) {
NSLog(#"Error calling sqlite3_prepare: %d", ret);
}
if(sqlite3_prepare_v2(database, sql, -1, &sqlStatement, NULL) == SQLITE_OK){
while (sqlite3_step(sqlStatement)==SQLITE_ROW) {
counterList *CounterList = [[counterList alloc]init];
CounterList.counterID = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement,0)];
[arrayOfCounters addObject:CounterList];
}
}
else{
NSLog(#"problem with database prepare");
}
sqlite3_finalize(sqlStatement);
}
else{
NSLog(#"problem with database openning %s",sqlite3_errmsg(database));
}
}
#catch (NSException *exception){
NSLog(#"An exception occured: %#", [exception reason]);
}
#finally{
sqlite3_close(database);
return arrayOfCounters;
}
//end
}
then i'm getting access to data with this and other similar lines of code:
myCounterList *MyCounterList = [[myCounterList alloc] init];
countersTempArray = [MyCounterList getCountersByID:"2"];
[countersArray addObject:[NSString stringWithFormat:#"%#",(((counterList *) [countersTempArray objectAtIndex:i]).counterID)]];
I'm getting a lot of data like image name and showing combination of them that depends on users input with such code:
UIImage *tempImage = [UIImage imageNamed:[NSString stringWithFormat:#"%#_0.jpg",[countersArray objectAtIndex:0]]];
[championSelection setBackgroundImage:tempImage forState:UIControlStateNormal];
My problem:
When i'm run my app for some time and get a lot of data it throws error: " problem with database openning unable to open database file - error = 24 (Too many open files)"
My guess is that i'm opening my database every time when getCountersByID is called but not closing it.
My question:
Am i using right approach to open and close database that i use?
Similar questions that did not helped me to solve this problem:
unable to open database
Sqlite Opening Error : Unable to open database
UPDATE:
I made assumption that error is showing up because i use this lines of code too much:
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *databasePath = [[[NSBundle mainBundle] resourcePath ]stringByAppendingPathComponent:#"DatabaseCounters.sqlite"];
BOOL success = [fileManager fileExistsAtPath:databasePath];
and ending up with error 24.
So i made them global but sqlite3_errmsg shows same err 24, but app runs much faster now
You should open your DB only once basically when you are in the initialization phase but not when you are requesting some info to your DB. Your code shouldn't failed though since you seems to open then close the DB after each request. Make sure this is happening by either logging those events or debugging through your code.
The code you've shown does close the database, so it's likely that you forget to close it in some other place, or that some other file is opened repeatedly but never closed.
I want to insert the data in a SQLite table login when a button is clicked, the problem is that when I click on the register button data is getting stored in variable but not in database table, and When I try to statically pass the value the data will be insert but When i trying to dynamically store data then not work.
Here is my code. Please go through it and help to solve this issue.
NSString *path;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask ,YES);
path = [paths objectAtIndex:0];
dbName = [[NSString alloc] initWithString:[path stringByAppendingPathComponent:#"mnc.sqlite"]];
NSFileManager *fileMgr = [NSFileManager defaultManager];
if([fileMgr fileExistsAtPath:dbName]== NO)
{
const char *dbPath = [dbName UTF8String];
if (sqlite3_open(dbPath,&connectionDB)==SQLITE_OK)
{
char *errMsg;
const char *sql_stmt = " create table if not exists login(user_name text ,password text)";
if (sqlite3_exec(connectionDB,sql_stmt,NULL,NULL,&errMsg))
{
printf("\n fail to create table ");
}
sqlite3_close(connectionDB);
}
else
{
NSLog(#"fail to open create database");
}
}
[fileMgr release];
if(sqlite3_prepare_v2(connectionDB, query ,-1, &statment,NULL) == SQLITE_OK)
{
sqlite3_bind_text(statment,1,"cc", -1,SQLITE_TRANSIENT);
sqlite3_bind_text(statment,2,"sa",-1,SQLITE_TRANSIENT);
NSLog(#"aadd");
}
if (sqlite3_step(statment)== SQLITE_DONE)
{
NSLog(#"This should be real error checking!");
sqlite3_finalize(statment);
}
It is quite complex to work with sqlite, thats why I use fmdb this will simplify the work.
This is an Objective-c wrapper around SQLite
Hope this helps.
I am new to iphone development,i was trying to insert the data in a sqlite table .but data is not inserted in the table.there was no error on the console.
NSString *string1=#"Test";
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"TestData" ofType:#"sqlite"];
if(sqlite3_open([filePath UTF8String], &database) == SQLITE_OK)
{
sqlite3_stmt *compiledStatement=nil;
char * sql = "insert into Test (title,summary,question,choice,answer) values (?,?,?,?,?)";
if (sqlite3_prepare_v2(database, sql, -1, &compiledStatement, NULL) == SQLITE_OK)
{
{
sqlite3_bind_text(compiledStatement, 1, [string1 UTF8String], -1,SQLITE_TRANSIENT);
sqlite3_bind_text(compiledStatement, 2,[string1 UTF8String] , -1,SQLITE_TRANSIENT);
sqlite3_bind_text(compiledStatement, 3, [string1 UTF8String], -1,SQLITE_TRANSIENT);
sqlite3_bind_text(compiledStatement, 4, [string1 UTF8String], -1,SQLITE_TRANSIENT);
sqlite3_bind_text(compiledStatement, 5, [string1 UTF8String], -1,SQLITE_TRANSIENT);
if(sqlite3_step(compiledStatement) != SQLITE_DONE )
{
NSLog( #"Error: %s", sqlite3_errmsg(database) );
}
else {
NSLog( #"Insert into row id = %d", sqlite3_last_insert_rowid(database));
}
}
As your database in resource bundle you are trying to modify and update it. The better approach would be place your database first time in documents directory of sandbox and then perform operation on that database.
Here is the method using which you can move your database to documents directory of your application's sandbox. This method should be called only once while using database operation.(because only first time we need to place it at that location, other times we just need to access it).
Code :
// Name : configureDatabase:
// Description : Method configures the database with new name.
// Arguements : NSString : Databse file name
// Retrun : None
-(void) configureDatabase:(NSString *)newDatabaseName
{
// Get the path to the documents directory and append the databaseName
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath = [[documentsDir stringByAppendingPathComponent:newDatabaseName]retain];
// Execute the "checkAndCreateDatabase" function
[self checkAndCreateDatabase:databasePath];
}
// Name : checkAndCreateDatabase:
// Description : Method checks and creates the database file at the given path if its not present.
// Arguements : NSString : file path.
// Retrun : None.
-(void) checkAndCreateDatabase:(NSString *)dbPath
{
// Check if the SQL database has already been saved to the users phone, if not then copy it over
BOOL success;
// Create a FileManager object, we will use this to check the status
// of the database and to copy it over if required
NSFileManager *fileManager = [NSFileManager defaultManager];
// Check if the database has already been created in the users filesystem
success = [fileManager fileExistsAtPath:dbPath];
// If the database already exists then return without doing anything
if(success)
{
return;
}
// If not then proceed to copy the database from the application to the users filesystem
// Get the path to the database in the application package
NSString *databasePathFromApp=[[NSBundle mainBundle] pathForResource:#"TestData" ofType:#"sqlite"];
// Copy the database from the package to the users filesystem
[fileManager copyItemAtPath:databasePathFromApp toPath:dbPath error:nil];
}
Also note that if we are using database so it is good practice to locate it first in some directory from where user can take backup. Documents directory of sandbox is one of these backup ready directory.
Thanks,
i have a database that is in the documents directorys of the
Application/iPhoneSimulator/3.2/Applications/etc/Documents
I have this code under my method
databaseName = #"database.sql";
NSArray *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory.NSUserDomainMask,YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
How do i do an insert with a variable/ array .
Something like
"INSERT INTO TABLE (COLUMN) VALUES ('%#'),[appDelegate.variable objectAtIndex:0];
I insist you to go through this question.
First of all copy the database from main bundle to your application's document dir.
You can follow below code to implement it.
NSString *databaseFile=[[NSBundle mainBundle] pathForResource:kDataBaseName ofType:kDataBaseExt];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
NSString *dbPath=[basePath stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.%#",kDataBaseName,kDataBaseExt]];
NSFileManager *fm=[NSFileManager defaultManager];
if(![fm fileExistsAtPath:dbPath]){
[fm copyItemAtPath:databaseFile toPath:dbPath error:nil];
}
[fm release];
self.dataBasePath=dbPath;
I am supplying you directly my project code. Please add comment if any doubts.
I have added comments for the explanation.
// function with multiple arguments which is going to be used for inserting into table.
+(void)insertBuilding:(NSString*)BName streetNo:(NSInteger)streetNo streetName:(NSString*)streetName streetDir:(NSString*)streetDir muni:(NSString*)muni province:(NSString*)province bAccess:(NSString*)bAccess bType:(NSString*)bType amnity:(NSString*)amnity latitude:(NSString*)latitude longitude:(NSString*)longitude imageName:(NSString*)imageName {
// application delegate where I have saved my database path.
BuildingLocatorAppDelegate *x=(BuildingLocatorAppDelegate *)[[UIApplication sharedApplication]delegate];
sqlite3 *database; // database pointer
// verifying if database successfully opened from path or not.
// you must open database for executing insert query
// i have supplied database path in argument
// opened database address will be assigned to database pointer.
if(sqlite3_open([[x dataBasePath] UTF8String],&database) == SQLITE_OK) {
// creating a simple insert query string with arguments.
NSString *str=[NSString stringWithFormat:#"insert into buildingDtl(b_name,streetNo,streetName,streetDir,muni,province,b_access,b_type,aminity,latitude,longitude,b_image) values('%#',%i,'%#','%#','%#','%#','%#','%#','%#','%#','%#','%#')",BName,streetNo,streetName,streetDir,muni,province,bAccess,bType,amnity,latitude,longitude,imageName];
// converting query to UTF8string.
const char *sqlStmt=[str UTF8String];
sqlite3_stmt *cmp_sqlStmt;
// preparing for execution of statement.
if(sqlite3_prepare_v2(database, sqlStmt, -1, &cmp_sqlStmt, NULL)==SQLITE_OK) {
int returnValue = sqlite3_prepare_v2(database, sqlStmt, -1, &cmp_sqlStmt, NULL);
((returnValue==SQLITE_OK) ? NSLog(#"Success") : NSLog(#"UnSuccess") );
// if NSLog -> unsuccess - that means - there is some problem with insert query.
sqlite3_step(cmp_sqlStmt);
}
sqlite3_finalize(cmp_sqlStmt);
}
sqlite3_close(database);
// please don't forget to close database.
}
+(NSString *)stringWithFormat:(NSString *)format parameters:...];
NSString sql = [NSString stringWithFormat:#"INSERT INTO table VALUES('%#')", #"Hello, world!"];
sqlite3_....
Use either prepared statements in combination with the bind_*() functions (e.g. bind_text()) or the mprintf() function to insert strings, see this question for details.
To get a raw C-string you can pass to these functions use -UTF8String or -cStringUsingEncoding: on a NSString.