Troubles with NSString writeToFile - iphone

I am using the following code to open a file's contents and save it to another file.
when it runs the original file length is 793 but the saved file is 0. I have also tried just to copy the file. Nothing seems to work.
Is there some kind of permissions I'm missing on the documents directory?
NSError *error;
NSString *basePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString* nGram = [basePath stringByAppendingPathComponent:#"contacts.gram"];
NSString *oGram = [basePath stringByAppendingPathComponent:#"/../vText.app/model/lm/TAR9230/contacts.gram"];
NSString *gramString = [[NSString alloc] initWithContentsOfFile:oGram encoding:NSUTF8StringEncoding error:&error];
BOOL ok = [gramString writeToFile:nGram atomically:NO encoding:NSUnicodeStringEncoding error:&error];
if(!ok) NSLog(#"Mayday!");
NSLog(#"%d",[gramString length]);
gramString = [[NSString alloc] initWithContentsOfFile:nGram encoding:NSUTF8StringEncoding error:&error];
NSLog(#"%d",[gramString length]);

This entire block is unnecessary. All you need is:
NSString *fp=[[NSBundle mainBundle] pathForResource:#"contacts" ofType:#"gram"];
NSString *gramString = [[NSString alloc] initWithContentsOfFile:fp
encoding:NSUTF8StringEncoding
error:&error];
You certainly don't want to try to directly access a file in the app bundle using a hardcoded path because the file isn't guaranteed to be in the same exact place in every build.
In the code you do have, you want to use the same encoding constant for reading as you did for writing. You write with NSUnicodeStringEncoding but you read with NSUTF8StringEncoding. These should overlap but why take the chance if you know the exact coding used?

Related

Rewriting problem while loggin in iPhone

i am using following code to log into a file...
NSData *dataToWrite = [[NSString stringWithString:#"log data"] dataUsingEncoding:NSUTF8StringEncoding];
NSString *docsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *path = [docsDirectory stringByAppendingPathComponent:#"fileName.txt"];
[dataToWrite writeToFile:path atomically:YES];
But when this method gets called again...it doest show the last entry...??
Could anyone suggest?
thanks
It is better you try using NSFileHandle , because the write operation to a file on NSData simply a convenience function and can not do a full fledged file operations like appending.

Store and Load File from URL

iPhone App
I am currently trying to understand how i can store a file from a URL to the documents directory and then read the file from the documents directory..
NSURL *url = [NSURL URLWithString:#"http://some.website.com/file"];
NSData *data = [NSData dataWithContentsOfURL:url];
NSString *applicationDocumentsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *storePath = [applicationDocumentsDir stringByAppendingPathComponent:#"Timetable.ics"];
[data writeToFile:storePath atomically:TRUE];
I got this code from http://swatiardeshna.blogspot.com/2010/06/how-to-save-file-to-iphone-documents.html
I want to know if this is the correct way to do this and i want to know how i can load the file from the documents directory into an NSString..
Any help will be greatly appreciated.
What you have looks correct, to read that file back into a string use:
EDIT: (changed usedEncoding to encoding)
NSError *error = nil;
NSString *fileContents = [NSString stringWithContentsOfFile:storePath encoding:NSUTF8StringEncoding error:&error];
Of course you should change the string encoding type if you are using a specific encoding type, but UTF8 is likely correct.
If you're doing this on your main thread, then no it's not correct. Any sort of network connection should be done in the background so you don't lock up the interface. For that, you can create a new thread (NSThread, performSelectorInBackground:, NSOperation+NSOperationQueue) or schedule it on the run loop (NSURLConnection).

How to load a txt file into an array

I coded a method to load a txt file into an array. However, I'm not really happy with it as it looks terribly cumbersome to my beginner's eyes (I'm sure I don't need 50% of my code) and I am somehow wondering how I can specify the exact format of my txt file, e.g. NSUTF8StringEncoding.
Here is my code:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents directory
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"Sample.txt"];
if (filePath) { // check if file exists - if so load it:
NSString *myText = [NSString stringWithContentsOfFile:filePath];
if (myText) {textView.text=myText;}
}
For any suggestions of how to polish this up and specify the right format, I'd be very grateful.
Try the following, assuming your file is in your bundle:
NSString * filePath = [[NSBundle mainBundle] pathForResource:#"Sample" ofType:#"txt"];
NSError * error = nil;
NSString * contentsOfFile = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:&error];
Into an array? You mean into a string, since is exactly what you're doing...
However, your code looks not bad, and most of it is just to grab the documents directory path, and that's not your fault, since it's exactly done this way, according to many knowledge bases.
As of the encoding, stringWithContentsOfFile is deprecated, please use stringWithContentsOfFile:encoding:error: (see the docs)
and you will be able to specify the correct encoding and get accurate error descriptions.

Load remote csv into CHCSVParser

I am using Dave DeLong's CHCSVParser to parse a csv. I can parse the csv locally, but I cannot get it load a remote csv file. I have been staring at my MacBook way too long today and the answer is right in front of me. Here is my code:
NSString *urlStr = [[NSString alloc] initWithFormat:#"http://www.somewhere.com/LunchSpecials.csv"];
NSURL *lunchFileURL = [NSURL URLWithString:urlStr];
NSStringEncoding encoding = 0;
CHCSVParser *p = [[CHCSVParser alloc] initWithContentsOfCSVFile:[lunchFileURL path] usedEncoding:&encoding error:nil];
[p setParserDelegate:self];
[p parse];
[p release];
Thanks for any help that someone can give me.
-[NSURL path] is not doing what you're expecting.
If I have the URL http://stackoverflow.com/questions/4636428, then it's -path is /questions/4636428. When you pass that path to CHCSVParser, it's going to try and open that path on the local system. Since that file doesn't exist, you won't be able to open it.
What you need to do (as Walter points out) is download the CSV file locally, and then open it. You can download the file in several different ways (+[NSString stringWithContentsOfURL:...], NSURLConnection, etc). Once you've got either the file saved locally to disk or the string of CSV in memory, you can then pass it to the parser.
If this is a very big file, then you'll want to alloc/init a CHCSVParser with the path to the local copy of the CSV file. The parser will then read through it bit by bit and tell you what it finds via the delegate callbacks.
If the CSV file isn't very big, then you can do:
NSString * csv = ...; //the NSString containing the contents of the CSV file
NSArray * rows = [csv CSVComponents];
That will return an NSArray of NSArrays of NSStrings.
Similar to this last approach is using the NSArray category method:
NSString * csv = ...;
NSError * error = nil;
NSArray * rows = [NSArray arrayWithContentsOfCSVString:csv encoding:[csv fastestEncoding] error:&error];
This will return the same structure (an NSArray of NSArrays of NSStrings), but it will also provide you with an NSError object if it encounters a syntax error in the CSV file (ie, malformed CSV).
I think you need an NSString, not an NSURL object to pass to the parser so the extra part you are doing with changing the NSString to an NSURL is the issue. Looking at the CHCSVParser documentation, it looks like he wants NSString in the init.
So maybe you could do something like:
NSError *err = [[[NSError alloc] init] autorelease];
NSString *lunchFileURL = [[NSString stringWithFormat:#"http://www.somewhere.com/LunchSpecials.csv"] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *lunchFile = [NSString stringWithContentsOfURL:[NSURL URLWithString:lunchFileURL] encoding:NSUTF8StringEncoding error:&err];
CHCSVParser *p = [[CHCSVParser alloc] initWithContentsOfCSVString:lunchFile usedEncoding:&encoding error:nil];

Logging in a text file iPhone

I have a score system and I would like to log all scores in a text file separated by line breaks. Here is my current save code:
NSData *dataToWrite = [[NSString stringWithFormat:#"String to write ID:%i \n",random] dataUsingEncoding:NSUTF8StringEncoding];
NSString *docsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *path = [docsDirectory stringByAppendingPathComponent:#"text.txt"];
// Write the file
[dataToWrite writeToFile:path atomically:YES];
When retrieving this data, I only see the latest save. How do I make it so it saves all in a list?
Thanks.
[dataToWrite writeToFile:path atomically:YES]; overwrites the file at that location, replacing whatever is there with the contents of dataToWrite.
You can likely use NSFileHandle's fileHandleForWritingAtPath: and then call seekToEndOfFile to append to said file.
Do you have an example?
Try something like:
NSFileHandle *f = [NSFileHandle fileHandleForWritingAtPath: p];
[f seekToEndOfFile];
[f writeData: d];
[f close];
All typed into SO; the compiler/runtime might differ with my opinions of correctness.