Save downloaded file with multiple subfolders on iOS - Objective C - ios

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

Related

Write to a file. Functional in the simulator and not functional on a real iphone [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);

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);

itunes file share restore deleted files

My app uses iTunes File Share. I used the code to delete a single file:
It worked the first time. On the second try, however, iTunes showed a empty share directory. It turns out all data files are gone. Can I recover those data files from the iPad? Thanks
- (void) deleteFileFromDisk: (NSString*) fileName {
if([self fileExists: fileName]) {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) ;
NSString *documentsDirectory = [paths objectAtIndex: 0];
NSString* theFile = [documentsDirectory stringByAppendingPathComponent: fileName];
NSError *error;
[[NSFileManager defaultManager] removeItemAtPath: theFile error: &error];
There's no "restore" feature on the iPad. But in all probability there's nothing to worry about.
There's nothing about your code that would delete multiple files. It would delete just that file from the Documents directory that you supplied the name of as fileName. If you didn't call deleteFileFromDisk: multiple times, you didn't delete multiple files.
Perhaps at some point you deleted the app. That would delete its entire sandbox and thus would take with it anything in the Documents directory. That sort of thing is perfectly normal during repeated testing.

Saving and loading an apps sql database

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];

NSFileManager UUID app directory

I'm using NSFileManager and i'm trying to copy a file to path "/var/mobile/Applications/7AC2295E-2775-41EA-B017-AB4048A09F0C/Document" the file will copy fine.
but the path of "7AC2295E-2775-41EA-B017-AB4048A09F0C" is randomly changed in every time i delete and install the app again. So, is there a way to get the correct path of my app or search for file name, If file exist then replace\delete..etc the file? thanks alot.
The proper way to get access to the Documents directory in your app's sandbox is:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = paths[0];
Then you create your path:
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"filename.ext"];
You don't have to use the absolute path, use something like
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0];
[[NSFileManager defaultManager] copyItemAtPath:[[NSBundle mainBundle]pathForResource:#"test" ofType:#"txt"] toPath:[documentsDirectory stringByAppendingPathComponent:#"test.txt"] error:nil];
This demonstrates copying the file test.txt from the apps bundle to the documents directory.
Do something like this to create a file test.txt
[[NSFileManager defaultManager] createFileAtPath:[documentsDirectory stringByAppendingPathComponent:#"test.txt"] contents:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://a-cstudios.com/text.json"]] attributes:nil];
EDIT
If your using this and want to use it on a jailbroken device, to put something in the sandbox is the same as I said before, so you still don't have to use the UUID. If you want to put something in a system directory, that is when you would use something like /usr/include/, or wherever you want to. To put something in another apps sandbox, you would have to use the complete path, and you would have to know the UUID, as thats not part of your sandbox. So, unless you're copying a file to an app that you made, you have to use the complete path.
If your application needs to write a file to its Documents directory.
use something like :
NSString *filePath = NSHomeDirectory();
then append your actual file name to filePath.
then use filePath in your FileManager calls.

Resources