Reputation: 3001
Background
I'm working on an app that calls a library my company has written previously in (plain) C. The main part of my app is written in Obj-C. At one point in the C code, the library needs to open and read data from a .txt file. The .txt file will be created by the Obj-C in the main part of the app.
The Issue
I can't get the C code to find the .txt file. Specifically, when i try to fopen
the file and assign it to a FILE
variable, the variable is always NULL
. Right now, the file is being written to the Documents folder of my app (but if that's the problem then I can change it). I've enabled file sharing, so I was able to verify with iTunes that the file is being written correctly and exists in the Documents folder.
My Attempts
Here's some of the code I've attempted so far.
In App:
NSURL *docs = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
const char *dir = [docs UTF8String];
myLibraryEntryPoint(dir,(int)[docs length]);
In Library:
char *new_str;
if ((new_str = malloc(strlen(directory)+strlen("/myFile.txt")+1)) != NULL)
{
new_str[0] = '\0';
strcat(new_str,directory);
strcat(new_str,"/myFile.txt");
}
else
{
fprintf(stderr, "malloc failed!");
}
FILE *fp=fopen(new_str, "r");
I've also tried the following in the library:
FILE *fp=fopen("Documents/myFile.txt", "r");
FILE *fp=fopen("/Documents/myFile.txt", "r");
FILE *fp=fopen("myFile.txt", "r");
FILE *fp=fopen("/myFile.txt", "r");
FILE *fp=fopen("Documents\myFile.txt", "r");
FILE *fp=fopen("Documents\\myFile.txt", "r");
FILE *fp=fopen("\Documents\myFile.txt", "r");
FILE *fp=fopen("\\Documents\\myFile.txt", "r");
As I said above, fp
is always NULL
after each of these attempts. What is the correct syntax in c to open a file in an iOS environment? I haven't made any changes in my Build Settings for my project to change the working directory, as covered in all of these questions, because unlike those questions, my app is creating the .txt file itself.
Resolution
Turns out file paths are case sensitive. My library was looking for myFile.TXT
, where my app was writing to myFile.txt
. FML.
I'm going to leave this question here, because I think there's some good information in the comments and the suggested answers about file path syntax and how the current directory is handled by the library. That information could be useful to others in the future.
Upvotes: 3
Views: 1346
Reputation: 2480
Was having a similar issue. I have a library in C from where I need to read-write files.
I wrote the code below to find the path to the Documents folder of the app:
char path[256] = {0};
strcpy(path, getenv("HOME"));
strcpy(path, "/Documents/file.txt");
FILE *file = fopen(path, "r");
Upvotes: 0
Reputation: 3955
The path to Documents
directory is accessible like this in objective-C:
NSString *documentsPath = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES)[0];
When using such a NSString path in C, you have to convert your NSString to UTF8 string:
NSString *fullPath = [documentPath stringByAppendingPathComponent:@"myFile.txt"];
File *f = fopen(fullPath.UTF8String, "r");
Be aware that fopen()
C function need to be passed the absolute path to the desired file to be able to open it.
If fopen()
returns NULL, you can check what went wrong by checking errno
for the error number and strerror()
function (from ) to have a human readable explanation:
#include <stdio.h>
#include <errno.h>
#include <string.h>
File *fileHandler = fopen( fullPathToFileAsUTF8String, openMode );
if( fileHandler == NULL ) {
fprintf(stderr, "File open error: %s\n", strerror(errno));
}
Upvotes: 1
Reputation: 1191
I think the problem with your first attempt is that you are passing a URL to a library function that expects a path. Try:
NSURL *docs = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
NSString *docsPath = docs.path;
const char *dir = [docsPath UTF8String];
myLibraryEntryPoint(dir,(int)[docsPath length]);
Upvotes: 0