Reading data from a file - objective-c

I'm new to mac and Cocoa so I'm sorry if this is a stupid question..
I need to read all the lines I wrote on a file I saved on my desktop.
The file format is .txt; I tried with stringWithContentsOfFile but the program freezes.
I tried with GDB and I noticed that, while the path is correct, the string which is supposed to contain the data returns nil.
Am I missing something important?

You need to use a path not just the filename
NSString *string;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
if ([paths count] != 0) {
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *newFile = [documentsDirectory stringByAppendingPathComponent:#"filename.txt"];
NSFileManager *fm = [NSFileManager defaultManager];
if ([fm fileExistsAtPath:newFile]) {
string = [NSString stringWithContentsOfFile:newFile];
}
}
You will need to replace the documents directory for the bundle directory if you are reading from there.
EDIT
I jumped the gun. It seems that this is NOT an iPhone question. None-the-less, you will need to pass in the full path, not just the filename

Related

Editing plist file(objective c)

I'm new to Objective C, and currently working on an iphone app. My app needs to take user inputs(strings) and store them, so I am using plist to store the data. Currently, I can read from the plist file. However, when I tried to write to the plist file, the file itself does not change at all.
What I'm trying to do is to append user's input to the existing plist file. So I read the plist file and store the array to a mutableArray. Then, I use the addObject function to append the new user input at the end of the mutableArray. Till this point, everything is working fine, and the mutableArray is exactly how I wanted it. The last step is what's not working for me:
[mutableArray writeToFile:[self dataFilePath] atomically:YES];
I assume that the my plist file(located in my resource folder along with the .h and .m files) should be changed after this line is executed and the new user input should be appended, but the file doesn't seem to change at all.
I have read some people say that I should copy the plist file from NSBundle to the Documents directory because the plist file is in the resource folder, but among almost all the tutorials on youtube, there has not been a problem like that and their code still work fine with their plist file in the resource folder.
Thank you in advance for your help.
Yes you must copy file from NSBundle to NSDocumentUser for example file "NimrokhRavanshenasi.sqlite3"
NSFileManager* fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDbtPath = [documentsDirectory stringByAppendingPathComponent:#"NimrokhRavanshenasi.sqlite3"];
BOOL success = [fileManager fileExistsAtPath:writableDbtPath];
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"NimrokhRavanshenasi.sqlite3"];
NSError *error;
success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDbtPath error:&error];
NSFileManager *filemgr = [NSFileManager defaultManager];
sqlite3_stmt *compiledStatement;
if([filemgr fileExistsAtPath:writableDbtPath]){
if (sqlite3_open([writableDbtPath UTF8String], &_contactDB) != SQLITE_OK) {
NSLog(#"Failed to open database!");

Get all files in Documents folder besides .DS_Store?

I am using this code to make an array with all the documents in the Documents folder of my app... Here is the code:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSArray *filePathsArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:documentsDirectory error:nil];
NSLog(#"files array %#", filePathsArray);'
How do I exclude .DS_Store from the array?
You can't exclude the .DS_Store files with that method, unless you want to do a second step, and filter them out of your filePathsArray. If you want to do it one step, then use contentsOfDirectoryAtURL:includingPropertiesForKeys:options:error:. You can pass nil for the properties and NSDirectoryEnumerationSkipsHiddenFiles for the options. You would also have to change the way you get path, and use URLsForDirectory:inDomains: to get the URL of the documents directory.
Will enumeratorAtURL: work for you? Here is the link http://disanji.net/iOS_Doc/#documentation/Cocoa/Conceptual/LowLevelFileMgmt/Articles/EnumADir.html

Unable to copy file from bundle to Documents directory, why does fileExistsAtPath return error?

I'm using the following snippet of code to attempt to copy a file from my application resources directory into the Documents area. I have used the below from the PocketOCR project on Github :
// Set up the tessdata path. This is included in the application bundle
// but is copied to the Documents directory on the first run.
NSString *dataPath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent:#"tessdata"];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSLog(#"Datapath is %#", dataPath);
// If the expected store doesn't exist, copy the default store.
if (![fileManager fileExistsAtPath:dataPath ]) {
NSLog(#"File didn't exist at datapath...");
// get the path to the app bundle (with the tessdata dir)
NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
NSString *tessdataPath = [bundlePath stringByAppendingPathComponent:#"tessdata"];
if (tessdataPath) {
[fileManager copyItemAtPath:tessdataPath toPath:dataPath error:NULL];
}
}
This is the output I get from invoking the above :
2012-06-06 14:53:42.607 MyApp[1072:707] Datapath is
/var/mobile/Applications/9676D920-D6D1-4F86-9177-07CC3247A124/Documents/tessdata
Error opening data file
/var/mobile/Applications/9676D920-D6D1-4F86-9177-07CC3247A124/Documents/tessdata/eng.traineddata
I have the eng.traineddata file located in my xcode project like so
It appears that the Error is being reported when attempting to check if fileExistsAtPath, I wouldn't expect this to throw an error, but to either return YES or NO.
Is there an easier way to copy the eng.traineddata file across, or have I made a mistake which can be corrected here?
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSString *dataPath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent:#"tessdata"];
NSLog(#"Datapath is %#", dataPath);
// If the expected store doesn't exist, copy the default store.
if ([fileManager fileExistsAtPath:dataPath] == NO)
{
NSString *tessdataPath = [[NSBundle mainBundle] pathForResource:#"eng" ofType:#"traineddata"];
[fileManager copyItemAtPath:tessdataPath toPath:dataPath error:&error];
}
-(NSString*) applicationDocumentsDirectory{
// Get the documents directory
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir = [dirPaths objectAtIndex:0];
return docsDir;
}
I hope also help this code to copy all type of file bundle to Document directory folder ..
NSString *pathsToReources = [[NSBundle mainBundle] resourcePath];
NSString *yourOriginalDatabasePath = [pathsToReources stringByAppendingPathComponent:#"lunchDB.sqlite"]; // file name u want copy
NSArray *pathsToDocuments = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [pathsToDocuments objectAtIndex: 0];
NSString *dbPath = [documentsDirectory stringByAppendingPathComponent:#"lunchDB.sqlite"]; // file name & your original path (Document path)
if (![[NSFileManager defaultManager] isReadableFileAtPath: dbPath]) {
if ([[NSFileManager defaultManager] copyItemAtPath: yourOriginalDatabasePath toPath: dbPath error: NULL] != YES)
NSAssert2(0, #"Fail to copy database from %# to %#", yourOriginalDatabasePath, dbPath);
}
Thanks ..
Use the method fileExistsAtPath:isDirectory: of NSFileManager and specify that the path is a directory, because it is.
stringByAppendingPathComponent:#"tessdata"
The line above required that tessdata is a physical folder (a blue color folder), not a group (yellow folder as you are showing) in Xcode project. Create a folder in your Xcode project folder using the Finder and then in Xcode drag and drop the folder to your project and select the folder reference when asked.

where does the text file I dragged to xcode go on the iphone/simulator?

I have some data in a .txt file that I dragged over to resources in xcode 4.2. I then use some methods that call upon this file, read it, and display it on the screen to the user. It works. My problem is writing to the end of the same file (aka updating the file based on something the user did) directly on the iphone/ the simulator. It does not write for I feel I am not calling upon the right location and perhaps method. This is my code to write to the end of file, if anyone knows why this is not working it would be tremendous help.
Thank you
-(void)updateFile:(id)sender
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//append filename to docs directory
NSString *myPath = [documentsDirectory stringByAppendingPathComponent:#"Mom.txt"];
fileHandle = [NSFileHandle fileHandleForUpdatingAtPath:myPath];
dateCombinedString= [dateCombinedString lowercaseString];
writtenString= [[NSString alloc]initWithFormat:#", %#, %#, %#",dateString,trimmedString,ForDisplay];
[fileHandle seekToEndOfFile];
[fileHandle writeData:[writtenString dataUsingEncoding:NSUTF8StringEncoding]];
[writtenString release]
}
The file you dragged to Xcode is inside your app resources. You can get the path to resource with this line of code:
NSURL* fileUrl = [[NSBundle mainBundle] URLForResource:#"Mom" withExtension:#"txt"];
However, you cannot modify the files in the resource directory therefore you should first copy that file to your document directory, then modify it with the code in the question.
Here is how you can copy file from resources if the file does not exist on the documents folder:
NSFileManager* fm;
fm = [NSFileManager defaultManager];
//only copy it from resources if it does not exits
if(![fm fileExistsAtPath:myPath]){
NSURL* myUrl = [NSURL fileURLWithPath:myPath];;
NSError* error = nil;
[fm copyItemAtURL:fileUrl toURL:myUrl error:&error];
//handle the error appropriately
}

Objective-C creating a text file with a string

I'm trying to create a text file with the contents of a string to my desktop. I'm not sure if I'm doing it right, I don't get errors but it doesn't work either...
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDesktopDirectory, NSUserDomainMask, YES);
NSString *desktopDirectory=[paths objectAtIndex:0];
NSString *filename = [desktopDirectory stringByAppendingString: #"file.txt"];
[myString writeToFile:filename atomically:YES encoding: NSUTF8StringEncoding error: NULL];
//Method writes a string to a text file
-(void) writeToTextFile{
//get the documents directory:
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//make a file name to write the data to using the documents directory:
NSString *fileName = [NSString stringWithFormat:#"%#/textfile.txt",
documentsDirectory];
//create content - four lines of text
NSString *content = #"One\nTwo\nThree\nFour\nFive";
//save content to the documents directory
[content writeToFile:fileName
atomically:NO
encoding:NSStringEncodingConversionAllowLossy
error:nil];
}
You don't know if you're getting any errors because you're ignoring the returned YES/NO value of the -writeToFile:... method, and giving it no error pointer into which to record any possible failure. If the method returns NO, you'd check (and handle or present) the error to see what went wrong.
At a guess, the failure is due to the path you constructed. Try -stringByAppendingPathComponent: instead of -stringByAppendingString: ... this and its related methods properly handle paths.
The file probably is actually being created (ie, you might not be getting any errors after all). My guess is the file is created somewhere like "~/Desktopfile.txt" since your use of -stringByAppendingString: doesn't consider the string as slash-separated path. Check your home folder - I'll bet the file's there.
the problem is that the desktop directory string ends in nothing (no /). Check this out (on an iPhone) by using UIAlertview.