How to use FILE * with iPhone - iphone

I have a file called "0.ballpoint" that all I want to do is store some coordinates with (don't really want to use Core Data because it seem a little excessive). I placed it in my project but when I try doing this:
if ( access("0.ballpoint", F_OK) != -1) {
printf("file exists\n");
}
else {
printf("doesn't exist\n");
}
It says it "doesn't exist". Do I need to put the full path name? And if I do what do I do when I place it on the actual iPhone/iPod Touch?

CoreData is not meant for File access. There are other file API's available for iPhone.
Please go through NSFileManager and NSStream documentation.
For example, if your intention is to check if file exists at certain path,you may use
(add your file to resources)
NSString *filePath = [[NSBundle mainBundle] pathForResource: #"0" ofType: #"ballpoint"];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:filePath];
Prefer not to use low level stuff (C File handles) unless you have a valid reason to do so. Paths are to be carefully chosen (as you cant make assumptions on certain path, which might cease to exist in future).
Having said that, if you prefer to work with C file handling ,
NSString *filePath = [[NSBundle mainBundle] pathForResource: #"0" ofType: #"ballpoint"];
FILE *fileHandle = fopen([filePath cStringUsingEncoding:NSASCIIStringEncoding],"r");

it needs to become a resource to your Application that way the file can be pulled anytime during the use of your application.
Im not too well educated in Ipod Dev, im more of a windows phone 7 developer but i know it cant access it if it is still on your computer so you need to import it into your application some how and call it with the full file path name.

Related

Accessing database file in xcode

I have an existing database file. I want to use this db file in a project. I placed this file in my app folder in mac and dragged the same into Xcode. And now I have written the code to check whether the file exists or not. But it is throwing FALSE exception.
bool databaseAlreadyExists = [[NSFileManager defaultManager] fileExistsAtPath:#"school.db"];
Please let me know how to use the existing db files.
Thanks
Try getting the path with
NSString *databasePath = [[NSBundle mainBundle] pathForResource:#"school" ofType:#"db"];
For Swift:
let dbPath = Bundle.main.path(forResource: "school", ofType: "db")
Without knowing what type of DB it is (MySQL, SQLITE, etc.) the best I can tell you is to find an iOS appropriate library/wrapper to access the database. As an example. FMBD if very good for SQLITE.
I suppose you're using Core Data in your project, aren't you?
If so take a look at the iPhone Core Data Recipes sample project by Apple!
In the Classes/​RecipesAppDelegate.m you'll find sample code for accomplishing what you need!
There's a good tutorial about pre-loading over at Ray Wenderlich's site.
Shipping a pre-loaded database in the way the Core Data Recipes example showcases is not the most desireable way by Apple. So please take a look at the provided tutorial for a more sophisticated approach!
It depends on whether or not you need the database to be writable.
You can get access to the database just by doing this:
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"mydb.sqlite"];
but if you've copied it to another directory so you can write to it (e.g. the Documents directory), you'd need to do something like this to get the path:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"mydb.sqlite"];

finding the path beyond the bundle

i want to find the path of the file which is not in my bundle..
NSString *path = [[NSBundle allBundle] pathForResource:nm ofType:#"jpg" inDirectory:nil];
but it gives warning that NSArray may not respond..
is there any way to find the path of file any other folder.
allBundle returns an NSArray of all the bundles. You mean to use the method mainBundle.
If you can't find your resource then this is most likely a problem with the name of the resource you're looking for (have you checked the value of nm is correct?) Also check in your Target under the "Copy resources" section that your .jpg file is listed there. If it's not then you should drag it there to ensure that the file is copied into your bundle when you build it.
If you really want to search through all the available bundles for your resource, then you can loop through the array of bundles that allBundle returns as follows:
NSString* pathForResource = nil;
for (NSBundle currentBundle in [NSBundle allBundle])
{
pathForResource = [currentBundle pathForResource:nm ofType:#"jpg"];
if (pathForResource)
{
break; // Found resource, no longer need to search through bundles.
}
}
Note: You also don't need to use the "inDirectory:" part of the method (see the docs).

Locally saved data files are persistant in the emulator but not in the real iPad device... I'm lost

I'm a (kind of) newbie XCode programmer (well, I would say not so newbie nowadays...) and "my pet issue" is: "I'm having trouble saving local files onto my real iPad, compared to saving them with the simulator".
Well to be honest, I have no problem whatsoever SAVING local files, but retrieving them. Why? Because on the simulator my local files seem to persist between compilation sessions, but on the real device, every time the application gets launched (not only after being uploaded from Xcode, but normally launched), data inside the "Documents" directory seems to disappear... So the final user would not be able to store needed historical data between sessions.
Is it a perception of mine? Is it normal behaviour?
The code I use to save this "persistent" data is this one:
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * documentsDir = [paths objectAtIndex:0];
NSString *finalPath=[NSString stringWithFormat:#"%#/%#", documentsDir, path];
NSLog(#"Course.m: updatePersistentObject (to disk): final file = %#",finalPath);
[NSKeyedArchiver archiveRootObject:newObject toFile:finalPath];
'path' variable being #".HistoricalTestResults";
The code I use to retrieve data (wheather at boot time, or at runtime) is this one:
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSLog(#" historical data: Documents paths = %#", paths);
NSString * docsDir = [paths objectAtIndex:0];
NSLog(#"Course.m: loadHistoricalResultsData: docsDir vale [%#]", docsDir);
NSString *tmpPath=[NSString stringWithFormat:#"%#/.HistoricalTestResults", (NSString *)docsDir];
NSLog(#"Course.m: loadHistoricalResultsData: tmpPath vale [%#]", tmpPath);
NSFileManager *localFileManager = [[NSFileManager alloc] init];
// create directory if it doesn't exist, don't do anything if it exists... (?)
[localFileManager createDirectoryAtPath:tmpPath withIntermediateDirectories:YES attributes:nil error:nil];
NSDirectoryEnumerator *dirEnum = [localFileManager enumeratorAtPath:tmpPath];
NSString *file;
while (file = [ dirEnum nextObject])
{
NSLog(#"Historical Data Folder: %#", file);
if ( [[file pathExtension] compare:#"dat"] == NSOrderedSame )
{
NSString *filePath = [NSString stringWithFormat:#"%#/%#", tmpPath, file];
NSLog(#"Course.m: loadHistoricalResultsData: filePath vale [%#]", filePath);
mHistoricalTestList=[[NSKeyedUnarchiver unarchiveObjectWithFile:filePath] retain];
}
}
[localFileManager release];
My exact problem is that while on the simulator, AT BOOT TIME, if I put a trace on the "while" code line, I can see how the enumerator gets some value, and I can iterate among the found files.
On the other hand, when using my iPad, the same breakpoint yields a "nil" pointer when obtaining the enumerator.
As I said, at the beginning of a clean program session, this is normal, so then I need to generate some storable results inside my program memory to store them onto disk.
I do it, and then I write them (both inside the simulator and the iPad). Then I can even re-retrieve this data (from disk) and it seems to still exist inside the Documents folder (both onto the iPad and the simulator).
But then, if I close/kill the program, this data seems to be lost onto the real iPad, and to persist in the simulator.
With this behaviour, my only deduction is "Real iPad programs cannot store persistent data onto their Documents directory". Am I right? (Of course not, because I've seen it work on some other programs).
So I have the feeling I'm doing something wrong, and after wasting TONS of time trying to find it, I'm now asking for advice on stackoverflow...
Every piece of help/insight/hint will be more than welcome.
Something I can think of is that your app is not being installed on the same app sandbox everytime. That means that while in the simulator your path is the same and the documents dir contains the same data, your ipad creates a new directory path for the installation, therefore the data you persisted in the last session won't be accessible.
Another thing that I experienced, was that the simulator was case insensitive when loading up resources, in contrast with the device that is actually case sensitive. In that time I had a strings file with extension .Strings and the iphone was looking for .strings. The simulator would work but the phone showed the keys when LocalizedString() macro was called.
So, tl;dr: verify the paths are the same in the different sessions, and your file names match.
I hope it helps. good luck!
PS: Gaudí rlz.
I'm happy! I was able to solve my own mess (!!?).
I've discovered that, when I originally copied my 2 code snippets, specially the "read part", I didn't copy it literally as it appears on my actual code, I just adapted some variable names and extra stuff that wasn't important here. (Typical situation)
I even did some more things than "removing some unrelated code pieces", (and here comes the important part), as I reordered some of them. And one of the parts I reordered was this one (which didn't work):
NSFileManager *localFileManager = [[NSFileManager alloc] init];
NSString *tmpPath=[NSString stringWithFormat:#"%#/.HistoricalTestResults", (NSString *)docsDir];
NSDirectoryEnumerator *dirEnum = [localFileManager enumeratorAtPath:tmpPath];
// create directory if it doesn't exist, don't do anything if it exists... (?)
[localFileManager createDirectoryAtPath:tmpPath withIntermediateDirectories:YES attributes:nil error:nil];
which I changed (when posting here), onto this other part (which works):
NSString *tmpPath=[NSString stringWithFormat:#"%#/.HistoricalTestResults", (NSString *)docsDir];
NSFileManager *localFileManager = [[NSFileManager alloc] init];
// create directory if it doesn't exist, don't do anything if it exists... (?)
[localFileManager createDirectoryAtPath:tmpPath withIntermediateDirectories:YES attributes:nil error:nil];
NSDirectoryEnumerator *dirEnum = [localFileManager enumeratorAtPath:tmpPath];
There's proably some logic behind this, as "why the first part does work on the emulator, but doesn't on the real device". It seems that "createDirectoryAtPath" is somewhat "resetting" some internal stuff, or maybe asking for an enumerator without having created a directory doesn't make sense...
Whatever the case is, I think my experience is worth enough to keep it here posted for someone who might be in my situation in the future!
Greetings again!

NSBundle returns nil

I wanted to read version information of my application from the plit file.
For this I am using a code as shown below.
NSString *myFilePath = [[NSBundle mainBundle]
pathForResource:#"MyApp-Info"
ofType:#"plist"];
// Format output
NSLog(#"%#",myFilePath);
The output
2010-08-31 17:14:10.095 MyApp[8759:20b] (null)
It always returns nil even if I tried to Import an existing file of type, text.txt still return nil, where text.txt is imported in the application.
I have goggled for the problem dont every one recommends to use NSBundel to read an pre imported file, but no use.
Any help, or an better way to read application version.
Got the solution via another link in the stack overflow here.
NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleVersion"];
NSLog(#"%#",version);
The reason this doesn't work is because pathForResource looks for stuff inside "MyApp.app/Contents/Resources". The Info.plist file does not reside inside the resources folder, so it's going to return nil if you look for it there. The correct way to get at it is to use the "infoDictionary" method on NSBundle.

Is possible to read plist from application bundle and documents folder at the same time?

Is it possible?to read from my local bundle and at the same time also read from documents folder into UItableview?
thanks thanks
yes.simultaneously
No — as in the iPhone isn't multicore, you can't have "simultaneous" :p
Yes — as in you can open multiple files in the same period of time. There's no conflicts as long as the files are different (if the files are the same then it depends on how others are using and locking the file etc.)
on viewDidLoad or some similar event when you would be populating your table data, you would simply just aggregate the two files together... that is you are are likely populating an array or dictionary with the contents of the file in question... so use the mutable version of array/dictionary, initialize it empty, then read in the first file from whatever location you choose, populating into your mutable array/dictionary, then do the the same for the next file. after you are done, reloadData as you normally would as if you had read form one file.
As far as simultaneous goes, technically no. However, one could have two different active threads each one reading required files and parsing the data.
Regarding the files you want to access...
Here is a quick and dirty method I use in one project (which I just happen to be working on at the moment):
NSFileManager* fileManager = [NSFileManager defaultManager];
NSError* error;
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
self.documentsDirectory = [paths objectAtIndex:0];
self.blahDBPath = [self.documentsDirectory stringByAppendingPathComponent: #"blah.db"];
NSLog(#"Mainbundle Resourcepath: %#", [[NSBundle mainBundle] resourcePath]);
NSString* defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"blah.db"];
NSLog(#"Default DB Path: %#", defaultDBPath);
success = [fileManager copyItemAtPath:defaultDBPath toPath:self.blahDBPath error:&error];
if (!success) {
NSAssert1(0, #"blah blah blah '%#'.", [error localizedDescription]);
}
It is ugly but effective. I'll rewrite it when I refactor the application.
The point here is that I ask the operating system for the path to certain directories. Then I add file names or subdirectories as required. This allows the operating system to manage paths (like in the simulator where each successive build gets a new unique id as part of its path) and I just worry about the final directories and file names in the application.
One I have the paths, I copy the required file from the bundle directory and put them somewhere, the Documents directory in this case. Then I can do whatever I need to with them.
If I just wanted to access them as they are in the bundle directory, then I I just refer to them by using [[NSBundle mainBundle] resourcePath].
I think something along the lines of the above snippet is what you are looking for.
-isdi-