Open file and read from file Objective-c
Asked Answered
C

6

7

I'm trying to open a file, and read from it.. but I'm having some issues.

FILE *libFile = fopen("/Users/pineapple/Desktop/finalproj/test242.txt","r");
char wah[200];
fgets(wah, 200, libFile);
printf("%s test\n", wah);

this prints: \377\376N test rather than any of the contents of my file.

any idea why?

complete code:

#import <Cocoa/Cocoa.h>
#import <stdio.h>

int main(int argc, char *argv[])
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

FILE *libFile = fopen("/Users/pineapple/Desktop/finalproj/test242.txt","r");
if(libFile){
char wah[200];
fgets(wah, 200, libFile);
printf("%s test\n", wah);
    }
[pool drain];
return 0;

}

And the test242.txt doesn't contain more than 200 chars.

Claudclauddetta answered 17/11, 2010 at 19:55 Comment(0)
I
16

If this is for Objective-C, why not do something like:

use NSFileHandle:

NSString * path = @"/Users/pineapple/Desktop/finalproj/test242.txt";
NSFileHandle * fileHandle = [NSFileHandle fileHandleForReadingAtPath:path];
NSData * buffer = nil;
while ((buffer = [fileHandle readDataOfLength:1024])) {
  //do something with the buffer
}

or use NSString:

NSString * fileContents = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];

or if you need to read it line-by-line:

How to read data from NSFileHandle line by line?

IMO, there's no need to drop down to the C-level fileIO functions unless you have a very very very good reason for doing so (ie, open a file using O_SHLOCK or something)

Inscrutable answered 17/11, 2010 at 20:4 Comment(2)
The goal is to read text from the file, word by word. I'm new to Objective-C, and (at least though) I knew how to manage text files using c functions.Claudclauddetta
This is correct. If the file doesn't necessarily contain string data (i.e. raw bytes) use an NSData object with its dataWithContentsOfFile constructor and you won't have to worry about NSString's automatic interpretation of string encodings.Holytide
I
6

Your file is stored in UTF-16 (Unicode). The first character in your file is "L", which is code point 0x4C. The first 4 bytes of your file are FF FE 4C 00, which are a byte-order mark (BOM) and the letter L encoded in UTF-16 as two bytes.

fgets is not Unicode-aware, so it's looking for the newline character '\n', which is the byte 0x0A. Most likely this will happen on the first byte of a Unicode newline (the two bytes 0A 00), but it could also happen on plenty of other non-newline characters such as U+010A (LATIN CAPITAL LETTER A WITH DOT ABOVE) or anything in the Gurmukhi or Gujarati scripts (U+0A00 to U+0AFF).

In any case, though, the data that's ending up in the buffer wah has lots of embedded nulls and looks something like FF FE 4C 00 47 00 4F 00 4F 00 0A 00. NUL (0x00) is the C string terminator, so when you attempt to print this out using printf, it stops at the first null, and all you see is \377\376L. \377\376 is the octal representation of the bytes FF FE.

The fix for this is to convert your text file to a single-byte encoding such as ISO 8859-1 or UTF-8. Note that must single-byte encodings (UTF-8 excepted) cannot encode the full range of Unicode characters, so if you need Unicode, I strongly recommend using UTF-8. Alternatively, you can convert your program to be Unicode-aware, but then you can no longer use a lot of standard library functions (such as fgets and printf), and you need to use wchar_t everywhere in place of char.

Idette answered 17/11, 2010 at 20:41 Comment(2)
... or just using something that understand UTF16 natively, like NSStringInscrutable
Ah Dave, you kids today with you fancy encodings, high-level frameworks and now even beat music, you're going to ruin our nice world...Musaceous
H
3

If you don't mind reading all of a file you can do something like this:

NSData* myData = [NSData dataWithContentsOfFile:myFileWithPath];

and then do whatever you'd like with the data from there. You will get nil if the file doesn't exist.

If you are assuming text (string) data in this file you can additionally do something like this and then parse it as a NSString:

NSString* myString = [[NSString alloc] initWithBytes:[myData bytes] length:[myData length] encoding:NSUTF8StringEncoding];

Since you mentioned you are relatively new to objective-c you can search NSStrings fairly well. Have a look here for more info on this.

Heteroclite answered 17/11, 2010 at 19:57 Comment(4)
I must have made this bug while trying to fix it. I edited to be printf("%s yeh\n", wah); and it has the same problemClaudclauddetta
paul is correct, there's little we can do without more information. Are you sure that your file exists and that fgets is reading data? Try setting wah to something first to make sure the garbage isn't just uninitialized data, somethhing like this: char wah[200] = "hello";Heteroclite
I tried initializing wah to something, it prints \377\376H test when the program runs. Also, i'm now checking, and the file definitely exists.Claudclauddetta
it sounds like this is an encoding issue. You're likely reading the data but sprintf is trying to print it as an ascii c-string, not as a unicode string. I'll update my post to include a NSString conversion from the NSData.Heteroclite
O
1

I wanted this as well and thought "do this instead" did not answer the question, here is a working example below. Beware that fgets reads the \n delimiter and appends to your text.

NSString * fName = [[NSBundle mainBundle] pathForResource:@"Sample" ofType:@"txt"];
FILE *fileHandle = fopen([fName UTF8String],"r");
char space[1024];
while (fgets(space, 1024, fileHandle) != NULL)
{
    NSLog(@"space = %s", space);
}

fclose(fileHandle);
Ovid answered 28/4, 2013 at 0:1 Comment(0)
J
0
 printf("%s test\n");

You're not passing the string to printf. Try

 printf("%s test\n", wah);

Also, if your file contains a line more than 200 characters long, fgets will read 200 characters into wah - then add a NUL to the end, which will be off the end of wah (since you declared it to be 200 characters) and will trample over something random, and the behaviour of your program will be undefined and may set fire to your cat.

Jordison answered 17/11, 2010 at 19:57 Comment(2)
I must have made this bug while trying to fix it. I edited to be printf("%s yeh\n", wah); and it has the same problemClaudclauddetta
Does your file exist? You're not checking the success of fopenJordison
S
0

Slycrel's got it. Expanding on that answer, here is another (in my opinion, simpler) way of turning that data into a string:

NSString *myFileString = [[NSString alloc] initWithData:someData encoding:NSUTF8StringEncoding];

This declares a new NSString directly using the NSData specified.

Schiffman answered 23/3, 2011 at 1:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.