In my app, I want to export a SQLite database file to CSV file..
Could you suggest me how to do this?
Thanks.
First, you'll want to make sure that you're using FMDB to access the database, because people who use the SQLite C API directly in Objective-C are masochists. You can do that like this:
FMDatabase *db = [[FMDatabase alloc] initWithPath:#"/path/to/db/file"];
FMResultSet *results = [db executeQuery:#"SELECT * FROM tableName"];
while([results nextRow]) {
NSDictionary *resultRow = [results resultDict];
NSArray *orderedKeys = [[resultRow allKeys] sortedArrayUsingSelector:#selector(compare:)];
//iterate over the dictionary
}
As for writing to a CSV file, well there's code for that too:
#import "CHCSV.h"
CHCSVWriter * csvWriter = [[CHCSVWriter alloc] initWithCSVFile:#"/path/to/csv/file" atomic:NO];
//write stuff
[csvWriter closeFile];
[csvWriter release];
And to combine them, you'd do:
FMDatabase *db = [[FMDatabase alloc] initWithPath:#"/path/to/db/file"];
if (![db open]) {
//couldn't open the database
[db release];
return nil;
}
FMResultSet *results = [db executeQuery:#"SELECT * FROM tableName"];
CHCSVWriter *csvWriter = [[CHCSVWriter alloc] initWithCSVFile:#"/path/to/csv/file" atomic:NO];
while([results nextRow]) {
NSDictionary *resultRow = [results resultDict];
NSArray *orderedKeys = [[resultRow allKeys] sortedArrayUsingSelector:#selector(compare:)];
//iterate over the dictionary
for (NSString *columnName in orderedKeys) {
id value = [resultRow objectForKey:columnName];
[csvWriter writeField:value];
}
[csvWriter writeLine];
}
[csvWriter closeFile];
[csvWriter release];
[db close];
[db release];
That will write the contents of the tableName table out to a CSV file.
Simply do a SELECT on each table and print out the value of each column as required to a text file.
Related
Below is the code i am using:
FMDatabaseQueue *queue = [[DataBaseHelper sharedManager] queue];
[queue inDatabase:^(FMDatabase *db) {
FMResultSet *results = [db executeQuery:#"select * from EVENT where ESTATUS='unread' and HIT_ATTEMPTS < 5 "];
if([results next])
{
[results close];
#try {
BOOL success=FALSE;
NSString *query=[NSString stringWithFormat:#"insert into EVENT (EDATA, ESTATUS ,EUSER) values('%#','%#','%#')",#"google.com",#"unread",#"xyz"];
success = [db executeUpdate:query];
NSLog(#"create edata row, %d:%#", [db lastErrorCode], [db lastErrorMessage]);
}
#catch (NSException *exception) {
NSLog(#"Exception");
}
In the above code
success = [db executeUpdate:query]; is not working. I have tried placing breakpoints. After this line of code all exits. None of the logs get printed.
I am not sure why you are using a try and Catch, anywayz follow the steps it will surely work
Creating A Database
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsPath = [paths objectAtIndex:0];
NSString *path = [docsPath stringByAppendingPathComponent:#"database.sqlite"];
FMDatabase *database = [FMDatabase databaseWithPath:path];
Opening The Database And Creating Tables(optional)
[database open];
//optional
[database executeUpdate:#"create table user(name text primary key, age int)"];
Querying The Database
FMResultSet *results = [database executeQuery:#"select * from user"];
while([results next]) {
NSString *name = [results stringForColumn:#"name"];
NSInteger age = [results intForColumn:#"age"];
NSLog(#"User: %# - %d",name, age);
}
[database close];
Below is a class to read and write data using nsarchive
Data.m
-(id)init {
self = [super init];
if(self) {
arr = [[NSMutableArray alloc] init];
}
return self;
}
-(NSString *)getPath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentPath;
if ([paths count] > 0)
documentPath = [paths objectAtIndex:0];
NSString *draftDataPath = [documentPath stringByAppendingPathComponent:#"draftData.dat"];
return draftDataPath;
}
-(void)saveDataToDisk {
NSString *path = [self getPath];
[NSKeyedArchiver archiveRootObject:arr toFile:path];
}
-(void)loadDataFromDisk {
NSString *path = [self getPath];
self.arr = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
}
At later on, I am adding some objects into arr by doing
CustomerClass.m
- (void) viewDidLoad {
Data *data = [[Data alloc] init];
[data.arr addObject:myObject1]
[data.arr addObject:myObject2]
[data.arr addObject:myObject3]
[data saveDataToDisk];
}
At DisplayData.m, I want to check data.arr by
- (void) viewDidLoad {
Data *data = [[Data alloc] init];
[data loadDataFromDisk];
NSLog(#"length of array is %d",[data.arr count]);
}
On the console, I am getting
length of array is 1
I thought it should be 3 after all.
Please point out what I have just made a mistake in the middle of work if you have any clues about it.
So, I suspect that your "myObjects" are not NSCoding compliant. I just did this:
NSMutableArray *arr = [NSMutableArray arrayWithCapacity:3];
[arr addObject:#"Hello"];
[arr addObject:#" "];
[arr addObject:#"World"];
BOOL ret = [NSKeyedArchiver archiveRootObject:arr toFile:[self getPath]];
NSArray *arr2 = [NSKeyedUnarchiver unarchiveObjectWithFile:[self getPath]];
NSLog(#"count = %d", [arr2 count]);
And the results was "count = 3"
I feel like there's too much code here to do what you're looking for. I think all you need is:
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:dataClass] forKey:NSUserDefaultString];
[[NSUserDefaults standardUserDefaults] synchronize];
to save it.
And:
NSData *someData = [[NSUserDefaults standardUserDefaults] objectForKey:NSUserDefaultString];
if (settingsData != nil)
{
dataClass = [NSKeyedUnarchiver unarchiveObjectWithData:settingsData];
}
to retrieve it.
I've made an app in which im using an sqlite database with fmdb wrapper for inserting and consulting data, the data is displayed into a table view, the problem is that when i run the app on an iphone 4 everything works well, but when i do it on an iphone 4s it doesn't..could someone please help me fix this issue.
Here are parts of my code:
Loading DB:
aPools = [[NSMutableArray alloc] init];
NSString *path = [[NSBundle mainBundle] pathForResource:#"poolsDB" ofType:#"sqlite"];
mainDB = [[FMDatabase alloc] initWithPath:path];
[mainDB open];
FMResultSet *fResult = [ mainDB executeQuery:#"SELECT * FROM poolsData"];
while ([fResult next]) {
poolsData = [fResult stringForColumn:#"Name"];
[aPools addObject:poolsData];
}
[mainDB close];
Saving :
-(void) saveIntoDB:(NSString *)name withVolume:(float)volume type:(NSString *)type andDesc:(NSString *)desc {
[mainDB open];
[mainDB executeUpdate:#"INSERT INTO poolsData (Name,Volume,Type,Desc) values (?,?,?,?)",name,
[NSNumber numberWithFloat: volume] ,type,desc, nil];
[mainDB close];
}
Could it be that the table view works in diferent ways beetwen devices?
Try the following code:
for LOADING:
aPools = [[NSMutableArray alloc] init];
NSString *path = [[NSBundle mainBundle] pathForResource:#"poolsDB" ofType:#"sqlite"];
FMDatabase* mainDB = [FMDatabase databaseWithPath:path];
if(![mainDB open])
{
return NO; //since the error in opening database
}
FMResultSet *fResult = [ mainDB executeQuery:#"SELECT * FROM poolsData"];
while ([fResult next]) {
poolsData = [fResult stringForColumn:#"Name"];
[aPools addObject:poolsData];
}
[mainDB close];
code for SAVING:
-(void) saveIntoDB:(NSString *)name withVolume:(float)volume type:(NSString *)type
andDesc:(NSString *)desc {
FMDatabase* mainDB = [FMDatabase databaseWithPath:path];
if(![mainDB open])
{
return; //since the error in opening database
}
[mainDB beginTransaction];
[mainDB executeUpdate:#"INSERT INTO poolsData (Name,Volume,Type,Desc) VALUES
(?,?,?,?)",name,
[NSNumber numberWithFloat: volume] ,type,desc];
[mainDB commit];
[mainDB close];
}
I have a problem when I add an arabic string to NSMutableArray or NSMutableDictionary.
Example:
NSMutableDictionary *data = [[NSMutableDictionary alloc]init];
[data setObject:#"فرسان" forKey:#"name"];
NSLog(#"%#",data);
Output:
2012-01-18 21:55:05.646 aa[367:207] {
name = "\U0641\U0631\U0633\U0627\U0646";
}
my problem exactly i save this data to sqlite [data objectForKey:#"name"] its saved \U0641\U0631\U0633\U0627\U0646 and when fetch data to to put it in UILabel or anything like it the text be \U0641\U0631\U0633\U0627\U0646
Any Help? Thank you :)
- (void)SaveMessage {
NSMutableDictionary *TableProperties = [[NSMutableDictionary alloc]init];
[TableProperties setObject:#"INSERT" forKey:#"Operation"];
[TableProperties setObject:#"savedmessages" forKey:#"tableName"];
NSString *string = [[NSString alloc]initWithFormat:#" %#",MessageBox.text];
[TableProperties setValue:string forKey:#"message"];
NSString *msgResult;
NSArray *result = [[DatabaseFunctions database] DataBaseOperation:TableProperties];
if ([[result objectAtIndex:0] isEqualToString:#"Done"])
msgResult = #"تم حفظ الرسالة بنجاح";
else
msgResult = #"لم تت العملية بنجاح حاول لاحقا";
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"حفظ الرسالة"
message:msgResult
delegate:self
cancelButtonTitle:#"موافق"
otherButtonTitles:nil, nil ];
[alert show];
}
- (NSArray *)DataBaseOperation:(NSMutableDictionary *)TableProperties{
NSMutableArray *retval = [[NSMutableArray alloc] init];
NSString *Operation = [TableProperties objectForKey:#"Operation"];
if ([Operation isEqualToString:#"SELECT" ]) {
NSString *tableColumns = [TableProperties objectForKey:#"tableColumns"];
NSString *tableName = [TableProperties objectForKey:#"tableName"];
NSString *tableWhere = [TableProperties objectForKey:#"tableWhere"];
NSString *tableOrder = [TableProperties objectForKey:#"tableOrder"];
NSString *tableLimit = [TableProperties objectForKey:#"tableLimit"];
NSString *Query;
if ([tableLimit isEqualToString:#"NO"]) {
Query = [[NSString alloc] initWithFormat:#"SELECT %# FROM %# WHERE %# ORDER BY %#",
tableColumns,tableName,tableWhere,tableOrder,tableLimit];
}else{
Query = [[NSString alloc] initWithFormat:#"SELECT %# FROM %# WHERE %# ORDER BY %# LIMIT %#",
tableColumns,tableName,tableWhere,tableOrder,tableLimit];
}
NSArray *FieldArray = [[TableProperties objectForKey:#"tableColumns"] componentsSeparatedByString:#","];
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(_database, [Query UTF8String], -1, &statement, nil) == SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
NSMutableDictionary *Row = [[NSMutableDictionary alloc]init];
NSString *uniqueId = [[NSString alloc] initWithFormat:#"%i",sqlite3_column_int(statement, 0)];
[Row setObject:uniqueId forKey:#"uniqueId"];
for (int i = 1; i<[FieldArray count]; i++) {
NSString *column = [[NSString alloc] initWithUTF8String:(char *) sqlite3_column_text(statement, i)];
[Row setObject:column forKey:[FieldArray objectAtIndex:i]];
}
Objects *rowOfTable = [[Objects alloc] initSelectDataFromTables:Row];
Row = nil;
[retval addObject:rowOfTable];
}
sqlite3_finalize(statement);
}
}
else if([Operation isEqualToString:#"INSERT" ]) {
NSString *tableName = [TableProperties objectForKey:#"tableName"];
[TableProperties removeObjectForKey:#"Operation"];
[TableProperties removeObjectForKey:#"tableName"];
NSArray *Columns = [TableProperties allKeys];
NSArray *Values = [TableProperties allValues];
NSString *Query = [[NSString alloc] initWithFormat:#"INSERT INTO %# %# VALUES %#",tableName,Columns,Values];
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(_database, [Query UTF8String], -1, &statement, nil) == SQLITE_OK)
if (SQLITE_DONE!=sqlite3_step(statement)){
NSLog(#"Error when inserting %s",sqlite3_errmsg(_database));
[retval addObject:#"Error"];
}else{
NSLog(#"Data inserted Successfully");
[retval addObject:#"Done"];
}
else{
NSLog(#"Error when inserting %s",sqlite3_errmsg(_database));
[retval addObject:#"Error"];
}
sqlite3_finalize(statement);
}
return retval;
}
When you log an object using %#, NSLog sends the description message to the object and prints the resulting string.
An NSDictionary responds to the description message by encoding its keys and values in a "safe" format, escaping non-ASCII characters using \U#### codes.
If you pass the Arabic string to NSLog directly, it will just print the string without the escape codes:
NSMutableDictionary *data = [[NSMutableDictionary alloc]init];
[data setObject:#"فرسان" forKey:#"name"];
NSLog(#"data = %#",data);
NSLog(#"string = %#", [data objectForKey:#"name"]);
Output:
2012-01-18 14:17:42.498 Animal[62723:f803] {
name = "\U0641\U0631\U0633\U0627\U0646";
}
2012-01-18 14:17:42.500 Animal[62723:f803] فرسان
If you don't like the way NSDictionary responds to description, you will have to write your own method to format a dictionary as a string and use it to log your dictionary.
Update
I have looked at the source code you posted that talks to sqlite. The problem is that you are turning the values array ([TableProperties allValues]) into a string using the %# format specifier. This sends the description method to the NSArray, which returns a string. Just like NSDictionary, NSArray formats the description string in a "safe" format, escaping non-ASCII characters using \U#### codes.
You need to write your own method that takes an array and turns it into a string and does not escape special characters. (It needs to escape quotes though.)
Friend it just general question .
How can write and retrieve the data on to the file .And how can make this file in .csv format.
For example i am retrieve data like that
NSString *coords = [[[NSString alloc] initWithFormat:#"%f,%f\n",longitude,latitude] autorelease];
[locations addObject:coords];
Than how can write this data on to the file in .csv format.
And than How can i retrieve this data
To write csv
NSString *coords = [[[NSString alloc] initWithFormat:#"%f,%f\n",longitude,latitude] autorelease];
NSData *csvData = [coords dataUsingEncoding:NSUTF8StringEncoding];
NSArray *UsrDocPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *DocsDir = [UsrDocPath objectAtIndex:0];
NSString *csvPath = [DocsDir stringByAppendingPathComponent:#"coords.csv"];
//This is upto your logic that do you want to remove existant csv file or not
BOOL success = [FileManager fileExistsAtPath:csvPath];
if(success){
[FileManager removeItemAtPath:csvPath error:&error];
}
[csvData writeToFile:csvPath atomically:YES];
To read from file
NSData *csvData = [NSData dataWithContentsOfFile:csvPath];
NSString *strCSV = [[NSString alloc]initWithData:csvData encoding:NSUTF8StringEncoding];
Hope it helps
There is a csv parser written by dave delong. you can use that.
First, you'll want to make sure that you're using FMDB to access the database, because people who use the SQLite C API directly in Objective-C are masochists. You can do that like this:
FMDatabase *db = [[FMDatabase alloc] initWithPath:#"/path/to/db/file"];
FMResultSet *results = [db executeQuery:#"SELECT * FROM tableName"];
while([results nextRow]) {
NSDictionary *resultRow = [results resultDict];
NSArray *orderedKeys = [[resultRow allKeys] sortedArrayUsingSelector:#selector(compare:)];
//iterate over the dictionary
}
As for writing to a CSV file, well there's code for that too:
#import "CHCSV.h"
CHCSVWriter * csvWriter = [[CHCSVWriter alloc] initWithCSVFile:#"/path/to/csv/file" atomic:NO];
//write stuff
[csvWriter closeFile];
[csvWriter release];
And to combine them, you'd do:
FMDatabase *db = [[FMDatabase alloc] initWithPath:#"/path/to/db/file"];
if (![db open]) {
//couldn't open the database
[db release];
return nil;
}
FMResultSet *results = [db executeQuery:#"SELECT * FROM tableName"];
CHCSVWriter *csvWriter = [[CHCSVWriter alloc] initWithCSVFile:#"/path/to/csv/file" atomic:NO];
while([results nextRow]) {
NSDictionary *resultRow = [results resultDict];
NSArray *orderedKeys = [[resultRow allKeys] sortedArrayUsingSelector:#selector(compare:)];
//iterate over the dictionary
for (NSString *columnName in orderedKeys) {
id value = [resultRow objectForKey:columnName];
[csvWriter writeField:value];
}
[csvWriter writeLine];
}
[csvWriter closeFile];
[csvWriter release];
[db close];
[db release];
That will write the contents of the tableName table out to a CSV file.
Then you can use CSV Parser to parse the CSV and get data.