Saving and loading an apps sql database - ios

I'd like to create a routine for the user to save their current version of my app's sqlite database into an app-specific folder in NSDocumentsDirectory, and then to generate a file list of saved sql files and load one of the file list (including the default file) as the working sql version. I'm reasonably familiar with core data, but this is my first foray into file archiving and retrieval. I've seen topics which cover saving NSData, but not Core Data SQL files. How do I do it?
Marcin - thanks. So if I have a UITextfield called fninput, is it like this?
NSString *path;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); path = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"inControl"];
NSString *filename = [fninput.text stringByAppendingString:#".sql"];
path = [path stringByAppendingPathComponent:filename];
[[NSFileManager defaultManager] createFileAtPath:path contents:nil attributes:nil];

Related

Can't modify file programmatically objective-c [duplicate]

I am trying to take content from one file and write it into another. I am reading fine, but I am not able to write it into another file.
I have a database of words. I want to separate the words into different files based on the number of letters. All four letter words go into one file, and so on. I added a txt file called "4letter" into my resources and the following is my code:
NSError *error;
//READ
NSString *dbFile = [[NSBundle mainBundle] pathForResource:#"words" ofType:#"txt"];
NSString *test = [NSString stringWithContentsOfFile:dbFile encoding:NSUTF8StringEncoding error:&error];
//convert from string to array
NSArray *lines = [test componentsSeparatedByString:#"\n"];
NSFileHandle *logFile = nil;
logFile = [NSFileHandle fileHandleForWritingAtPath:[[NSBundle mainBundle] pathForResource:#"4letter" ofType:#"txt"]];
//Test if write works
for (int i=0; i<5; i++)
{
NSString *randomAnagram = [[lines objectAtIndex:i] lowercaseString];
[logFile writeData: [randomAnagram dataUsingEncoding: NSNEXTSTEPStringEncoding]];
}
In iOS, you can't write into a file in your app's bundle -- the entire bundle is read-only. Use a path into the Documents folder instead.
See special File System Programming Guide for better understnading.
In iOS, you can't write into a file in your app's bundle -- the entire bundle is read-only.
Consider reading iOS Data Storage Guidelines to better understand the purpose of directories below, in context of iCloud backup.
<Application_Home>/AppName.app
This is the bundle directory containing the app itself. Do not write
anything to this directory. To prevent tampering, the bundle directory
is signed at installation time. Writing to this directory changes the
signature and prevents your app from launching again.
<Application_Home>/Documents/
Use this directory to store critical user documents and app data
files. Critical data is any data that cannot be recreated by your app,
such as user-generated content. The contents of this directory can be
made available to the user through file sharing. The contents of this
directory are backed up by iTunes.
<Application_Home>/Library/
This directory is the top-level directory for files that are not user
data files. You typically put files in one of several standard
subdirectories but you can also create custom subdirectories for files
you want backed up but not exposed to the user. You should not use
this directory for user data files. The contents of this directory
(with the exception of the Caches subdirectory) are backed up by
iTunes. For additional information about the Library directory, see
“The Library Directory Stores App-Specific Files.”
See full list (tmp/, Documents/Inbox) in iOS Standard Directories: Where Files Reside
UPDATE
I use NSFileManager method URLForDirectory:inDomain:appropriateForURL:create:error:
Like Caleb said, you can't write to your app's directory, but you can write to your app's Documents folder. You can get it like this:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
Your app's bundle is read-only. There is two ways I could see:
1) Write in documents folder:
NSArray *pathList = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path =  [myPathList  objectAtIndex:0];
2) Use sqlite database. This is the same as 1 (you must save db in documents anyway), but you're using sqlite database. I think this is better than a lot of txt and plist files: here's a tutorial on the topic.
I use the following code :
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *appFile = [documentsDirectory stringByAppendingPathComponent:#"set.txt"];
NSString *data=#"Kostas";
[data writeToFile:appFile atomically:YES];
NSString *myData = [NSString stringWithContentsOfFile:appFile];
NSLog(#"Data : %# ",myData);

How to store audio file in sqlite database in iOS

I am developing an iPhone application for an audio player. I want to give some options to the user so they can listen to the song/music by streaming or they can download the audio file and store in sqlite database. I know how to stream the audio files in the app programmatically. But I don’t know how to store the downloaded audio file in sqlite database using BLOB. Additionally, after storing the audio file in the sqlite DB I need to fetch the audio file and play the song. How do I fetch the audio file from sqlite DB?
This is my code for downloading the audio file.
NSURL *url = [NSURL URLWithString:#"http://www.fileurl.com/example.mp3"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadDestinationPath:[NSString stringWithFormat:#"%#",dataPath]];
[request setDelegate:self];
[request startAsynchronous];
I don't recommend to store binary files in database as blobs.
it will make you a problem with growing database file size in future. You will have to implement smart vacuum operation which is very slow on large data amounts.
My strong opinion: the files must be stored in file system. Store your file in application Documents folder and store a kind of link to them in database.
you can download file and write audio file using NSDocumentDirectory in app. Documents folder like
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"audio.mp3"]];
[{your audio file in NSData} writeToFile:path atomically:YES];
now store only "audio.mp3" in database
when you retrieve data from database that give you name like
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:{database store name}]];
note if you store full path that not working because Documents foldar path change whenever you run app.

How do I dump SQLite programmatically without command line

In my app, I would like to recognize when the database has been damaged and automatically repair it. Specifically, when the app is first opened I run an ANALYZE command and if it comes back with status 11 (database disk image is malformed), then I would like to have a way of recovering the data.
All the examples I find use the terminal to do a dump and then import of the subsequent SQL command file.
How can I do a dump of the db from within my own code since the command line isn't available on iOS?
Thanks
I think you can easily copy and save the database with another name (extend timestamp). You have to figure out when it is damaging(It should not damage it depends on your meaning of damage) and replace it.
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *sqlpath = [documentsDirectory stringByAppendingPathComponent:#"Your-sqlitefile"];
NSString *sqldump = //append timestamp
[fileManager copyItemAtPath:sqlpath toPath:sqldump error:&error];
Edit:
Please refer below answer. I have not used by myself but hope it helps.
https://stackoverflow.com/a/27453637/1881472

Save downloaded file with multiple subfolders on iOS - Objective C

My project requires to download a Gzip file from the Internet, that contains multiple subfolders in a tree structure and images on the last folders, and save all the structure with subfolders and images on Documents Directory.
Root_Folder/
Folder_Level_1/
Folder_Level_2/
Image
Folder_Level_2/
Image
Folder_Level_1/
Folder_Level_2/
Image
Folder_Level_2/
Image
Download and compression work fine, the problem is when I try to save the content on the documents directory, as it threats all the content if it was a single file.
NSData *data = ...uncompressed file...
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"FileName"];
BOOL success = [[NSFileManager defaultManager] createFileAtPath:path
contents:data
attributes:nil];
I don't even know if it's possible to save the structure of subfolders I am trying to save... If it's possible, what's wrong on my code and what's the proper way to do it?
Thanks

Xcode IOS How To Access Files With Unknown Filename

My app allows users to create and delete files from the documents folder within the app. They can do it through the app itself or manually using itunes. Is there are way to access what's left in the documents folder without any hardcoding of the filenames?
Thank you.
You can get NSArray with all items in given directory using contentsOfDirectoryAtPath:error: method in NSFileMamanger:
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSArray *allItems = [[NSFileManager sharedFileManager] contentsOfDirectoryAtPath:documentsDirectory error:NULL];

Resources