How to save text/data in cocoa/xcode to a file? - objective-c

i'm sorry for the obvious question, but is there something i should be careful about when writing data to a file, because my program can read the data it just wrote, while the program is running, but the moment i stop it, the files become empty
tried using NSFileHandle, in order to write data with it, and close the file later, didn't help... currently, i'm using:
NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:newArray];
[encodedObject writeToFile:string atomically:YES];
and no matter what i do, i can't get the simplest NSString to stay in the file permanently
what do i do?
Thanks #LetzFlow, but it didn't solve it just yet.
Now, i'm using:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
string = [NSString stringWithFormat:#"%d.rtf",fileName];
NSString *file = [documentsDirectory stringByAppendingPathComponent:string];
//NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:file];
NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:newArray];
[encodedObject writeToFile:file atomically:YES];
//[fileHandle writeData:encodedObject];
//[fileHandle closeFile];
NSLog(#"%#",[NSString stringWithContentsOfFile:file encoding:NSStringEncodingConversionAllowLossy error:nil]);
to serialize an array of objects, and it the NSLog shows a valid array. Yet, when I look at the file later, or try to unserialize the array (like this):
NSString *stringX = [NSString stringWithFormat:#"%d.rtf",fileName];
NSData *encodedObjectX = [NSData dataWithContentsOfFile:stringX];
NSArray *newArrayX = [NSKeyedUnarchiver unarchiveObjectWithData:encodedObjectX];
TurnigButton *button = [[newArrayX objectAtIndex:1] objectAtIndex:5];
NSLog(#"%d", button.idNum);
it just prints (null). (when they execute one after the other in a single run, it unserializes just fine)
I appreciate the help.

The question is WHERE do you write your file? Because you are not allowed to write files all over the system in iOS.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
The documents directory is usually a place were you can write files, so you might want to give that a try.

Related

How can I read user input text from a textfield and write it to a text file in Xcode?

Is there a way to write a string , which is read from text field, to a .txt file?
NSString *input = [textfield text];
NSString *path = #"myText.txt";
[input writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:NULL];
Yes, ultimately that is the way; but there's a number of other steps you do in order to get from start to finish (you need to have textfield connected to an IBOutlet or in some other way accessible; the path where myText.txt is writing to needs to be writable and therefore you'd probably need to have a longer, more precise path than just the filename; you'd probably need to also send in an actual error parameter that could be set so you could look at the errors being returned when the writeToFile call fails the first few times you run this code).
You will need to define a path, basically where to save the file.
This code will find the Documents folder
NSArray *path = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirPath = [path objectAtIndex:0];
Here is the code I use to read and write files.
-(void)writeFileToDisk:(id)data
{
NSArray *path = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirPath = [path objectAtIndex:0];
NSString *fileName = #"MyFileName.txt";
NSString *fileAndPath = [documentDirPath stringByAppendingPathComponent:fileName];
[data writeToFile:fileAndPath atomically:YES];
}
-(void)readFileFromDisk
{
NSArray *path = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirPath = [path objectAtIndex:0];
NSString *fileName = #"MyFileName.txt";
NSString *fileAndPath = [documentDirPath stringByAppendingPathComponent:fileName];
NSArray *array = [[NSArray alloc] initWithContentsOfFile:fileAndPath];
NSLog(#"%#",array);
[array release];
}

objective-c simple nsarray writeToFile issue

[wordlist writeToFile:[[NSBundle mainBundle]
pathForResource:#"wordlist" ofType:#"txt"] atomically: YES];
wordlist is a NSMutableArray, and the rest you know what.
The problem is that nothing is saved in wordlist.txt when I run the codes in Xcode. In front of this code nslog shows that there are 4 objects in wordlist. How come?
Edit:
Right!
These codes work!:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *yourArrayFileName = [documentsDirectory stringByAppendingPathComponent:#"wordlist.txt"];
[wordlist writeToFile:yourArrayFileName atomically:YES];
NSLog (#"%#", yourArrayFileName);
Edit 29 august 2011.
NSString *documentsDirectory = #"/Users/YOURNAME/Desktop/";
NSString *appFile = [documentsDirectory stringByAppendingPathComponent:#"norsk.txt"];
NSString *content = #"æ ø å";
BOOL ok = [content writeToFile:appFile atomically:YES encoding:NSUnicodeStringEncoding error:nil];
if (!ok) {
NSLog(#"Error writing file !");
}
also works!
You can't write in you app's bundle.
You need to write in the user's directory. You can know more about it in this question.
There's three directory you can write in
NSDocumentDirectory : the document directory. The user will be able to see these file. This should be for user files only. Backed up by iTunes.
NSCachesDirectory : the cache directory is where you place things you app may need in the future, but that you can reconstruct. Not backed up by iTunes.
NSApplicationSupportDirectory : the application support is where you place your essential files for your application. Backed up by iTunes.

writeToFile:atomically only works first time

When my app starts, looks if a plist exists, if it doesn't it creates it.
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"history.plist"];
success = [fileManager fileExistsAtPath:filePath];
if (success) {
NSArray *arr = [[NSArray alloc] initWithContentsOfFile:[documentsDirectory stringByAppendingPathComponent:#"history.plist"]];
for (NSDictionary *par in arr) {
[self.history addObject:[[Paradero alloc] initWithDictionary:par]];
}
} else {
[fileManager createFileAtPath:filePath contents:nil attributes:nil];
}
Now, when the user closes the app, to provide persistance I save the data to that file
- (void)applicationDidEnterBackground:(UIApplication *)application {
/*
Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
If your application supports background execution, called instead of applicationWillTerminate: when the user quits.
*/
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"history.plist"];
NSLog(#"%#", filePath);
NSMutableArray *temparray = [[NSMutableArray alloc] initWithCapacity:5];
for (Paradero *parada in self.history) {
[temparray addObject:[parada asDictionary]];
}
NSLog(#"%#", temparray);
NSLog(#"%c",[temparray writeToFile:filePath atomically:NO]);
NSLog(#"yei");
}
The object is converted to a Dictionary with NSString, NSArrays so it can be saved to the file. The first time this ever happens, that means, the file was created, nothing on it, it works just fine, but when is time to save new data, it fails, no reason given.
Solved.
For the record:
The first issue was that i was testing on iOS5 Simulator, well, i don't know how to fix it there yet.
The real issue was because there was some NSNull around, so, I just needed to turn them into empty strings.
Remember to check for NSNulls, they are really a pain if they turn out from a web service.

Accessing NSDocumentDirectory on iPad Simulator

I've added a very simple .csv file to my app's NSDocumentDirectory using:
-(IBAction)exportModule:(id)sender{
NSString *fileName = #"exportedfile.csv";
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *exportString = #"I've,been,exported";
NSData *testData=[exportString dataUsingEncoding:NSUTF8StringEncoding];
NSString *docDir = documentsDirectory;
NSString *completePath = [docDir stringByAppendingPathComponent:fileName];
[testData writeToFile:completePath atomically:YES];
if ([[NSFileManager defaultManager] fileExistsAtPath:completePath]) {
NSLog(#"Theres a file here!");
}
}
The app gets into the if statement printing "Theres a file here!", however I would like open the file and see if there were any problems in formatting the .csv.
If I were running on a physical device, I'd be able to open it up in iTunes and take a look there, but is there a way to examine the .csv while only using the simulator?
I have this at the beginning of all of my programs for using the simulator
NSLog(#"Documents: %#", [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]);

Save NSDictionary to plist

I am using the code found in this post: Mulitple Arrays From Plist, with the same plist formatting.
This works successfully, however I do not know how to save the created arrays back into a plist, in the same format.
How would I achieve this?
EDIT: It is not so much the saving that I need, but the forming of the data to save.
The plist is an array of dictionaries with strings and their corresponding keys.
All the strings with a certain key are put into an array of their own.
How would I put that array back into the correct positions in the array of dictionaries, ready to save?
Here's the simplest way:
NSDictionary* dict = ...;
[dict writeToFile:#"..." atomically:YES];
See the documentation for -writeToFile:atomically:.
Don't forget to create myPlistFile.plist and add it in your application resource folder.
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
you could scan paths here and search myPlistFile.plist using for loop.
NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:#"myPlistFile.plist"];
if (![[NSFileManager defaultManager] fileExistsAtPath: plistPath])
{
NSString *bundle = [[NSBundle mainBundle] pathForResource:#"myPlistFile" ofType:#"plist"];
[[NSFileManager defaultManager] copyItemAtPath:bundle toPath:plistPath error:&error];
}
[myDict writeToFile:plistPath atomically: YES];
And conversely, to load a NSDictionary FROM a file:
+ (id)dictionaryWithContentsOfFile:(NSString *)path;