GeneralMike GeneralMike - 2 months ago 19
C Question

Read .txt file in .c file for iOS

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.

Answer

The path to Documentsdirectory 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));
}
Comments