Is it possible to read and write to a .h file with objective c? - objective-c

I'm trying to make an xcode plugin that needs to write something to the .h file from the .m file. I haven't been able to find a stackoverflow post with an answer on how to do this. I've tried this code
NSData *data = [NSData dataWithContentsOfFile:filePath];
NSString *contents = [[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF8StringEncoding];
I've also tried using the StringWithContentsOfFile method, however they both return nil. Is it because you can't read an .h file with this code or is it something else I'm missing.
filePath is this and it's a correct filepath, my ftp client can read it atleast file:///Users/myUserName/Documents/code/macOsDev/XcodePlugIns/XcoderPlugin/XcoderPlugin/XcoderPlugin.h
So my question is, how do I read and write to a .h file? Thanks in advance.
EDIT as requested, some more code however this is as far as I've gotten to the read/write part of my plugin.
NSString *filePath = path;
NSData *data = [NSData dataWithContentsOfFile:filePath];
NSString *contents = [[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF8StringEncoding];
NSError *error;
NSString *contents1 = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:&error];
contents is #"" because data is nil
and contents1 is just nil;
error is error
NSError * domain: #"NSCocoaErrorDomain" - code: 260
in the debugger, but I'm not sure I'm using this error thing correctly.

Use "/Users/myUserName/Documents/code/macOsDev/XcodePlugIns/XcoderPlugin/XcoderPlugin/XcoderPlugin.h".
Dont use 'file://' prefix
Following is the code for reading and writing
NSString *path = #"your/path/tp/.h/file";
NSData *data = [NSData dataWithContentsOfFile:path];
//Get the contents of the file into the mutable string
NSMutableString *contents = [[NSMutableString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF8StringEncoding];
//Make changes to your mutable string
[contents appendString:#"abc"];
//Write it back to the file
[contents writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:nil];

Related

.m file to string

I am trying to convert a .m file to string. I will search for files in a folder and then want to use each of its contents as a string. This is the code I am using:
- (IBAction)searchAction:(id)sender {
NSFileManager *fm = [NSFileManager defaultManager];
NSArray *dirContents = [fm contentsOfDirectoryAtPath:folderLabel.stringValue error:nil];
NSPredicate *fltr = [NSPredicate predicateWithFormat:#"self ENDSWITH '.m'"];
NSArray *onlyMs = [dirContents filteredArrayUsingPredicate:fltr];
for (int i=0; i<[onlyMs count]; i++) {
NSString* text = [[NSString alloc] initWithContentsOfFile:[onlyMs objectAtIndex:i]
encoding:NSUTF8StringEncoding
error:nil];
NSLog(#"string: %#", text);
}
}
2013-02-13 02:38:05.700 LocalizedStringSearch[19001:303] string: (null)
Except here, all the log is returning is null even though it will find all the .m file correctly.
Anyone know what I'm doing wrong?
Thanks a lot!
I think contentsOfDirectoryAtPath: gives you an array of filenames only, not full path names, so you need to prepend the path before you open files. EDIT: I think I might be confusing that with enumeratorAtPath:... if so continue using the filenames you have rather than appending them to the original folder name.
Here's an example (untested):
NSString *fullPath = [folderLabel.stringValue stringByAppendingPathComponent:[onlyMs objectAtIndex:i];
NSError *error = nil;
NSString *text = [[NSString alloc] initWithContentsofFile:fullPath
encoding:NSUTF8StringEncoding
error:&error];
if (text == nil)
NSLog(#"%#", error);
else
NSLog(#"%#", text);
The above will only work if the files actually are encoded using UTF-8. If you are unsure of the encoding, you can let the framework try and figure it out for you with:
NSString *fullPath = [folderLabel.stringValue stringByAppendingPathComponent:[onlyMs objectAtIndex:i];
NSError *error = nil;
NSStringEncoding enc;
NSString *text = [[NSString alloc] initWithContentsofFile:fullPath
usedEncoding:&enc
error:&error];
if (text == nil)
NSLog(#"%#", error);
else
NSLog(#"%#", text);

Can't figure out about saving files

I am trying to save my object to the file system on an iPad, but I seem to be doing something wrong. Here is how I have archived the object:
NSString *localizedPath = [self getPlistFilePath];
NSString *fileName = [NSString stringWithFormat:#"%#.plist", character.infoName];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:character];
fileName = [fileName stringByReplacingOccurrencesOfString:#" " withString:#"_"];
localizedPath = [localizedPath stringByAppendingPathComponent:fileName];
NSLog(#"File Path: %#", localizedPath);
if(data) {
NSError *writingError;
BOOL wasWritten = [data writeToFile:localizedPath options:NSDataWritingAtomic error:&writingError];
if(!wasWritten) {
NSLog(#"%#", [writingError localizedDescription]);
}
}
Now, this creates a plist file that I can see and read on the file system. When I try to use the following to unarchive it though:
NSError *error;
NSString *directory = [self getPlistFilePath];
NSArray *files = [[NSFileManager defaultManager]contentsOfDirectoryAtPath:directory error:&error];
NSMutableArray *characters = [[NSMutableArray alloc]init];
for(NSString *path in files) {
if(![path hasSuffix:#"plist"]) {
continue;
}
NSString *fullPath = [directory stringByAppendingPathComponent:path];
NSData *data = [NSData dataWithContentsOfFile:fullPath];
IRSkillsObject *object = [NSKeyedUnarchiver unarchiveObjectWithData:data]; // get EXEC_BAD_ACCESS here...
[data release];
[characters addObject:object];
}
I get an EXEC_BAD_ACCESS error.
The IRSkillsObject conforms to the NSCoding protocol. You can see, I commented the line that I get the error on.
I am sure it's something I am doing wrong, but I just can't see it. I have tried to step through with the debugger (placing a break point in the initWithCoder: method of the object) but I don't get any errors then. In fact, it places the data in the object properly as I watch. But once it's done loading the data, it gives the error. I have tried using the retain method, but that doesn't help.
Any help that you can provide would be greatly appreciated!
You are releasing data without allocating it.
NSData *data = [NSData dataWithContentsOfFile:fullPath];
IRSkillsObject *object = [NSKeyedUnarchiver unarchiveObjectWithData:data];
[data release];
So try this:
NSData *data = [[NSData alloc] initWithContentsOfFile:fullPath];
IRSkillsObject *object = [NSKeyedUnarchiver unarchiveObjectWithData:data];
[data release];
When an EXEC_BAD_ACCESS error is found. Usually is because some data has been released but it is still needed in the code.
Maybe there is a property inside your IRSkillsObject not retained in -initWithCoder:

Crash on writeToFile

I'm using quite a simple method of storing file names in a text file. For some reason when I initiate the writeToFile I get a crash:
pathString = [NSString stringWithFormat:#"New FileName - %#.png", identifier];
NSString *currentContents = [NSString stringWithContentsOfFile:saveFilePath encoding:NSUTF8StringEncoding error:nil];
NSString *newContents = [NSString stringWithFormat:#"%#:::%#",currentContents, pathString];
NSData *newData = [newContents dataUsingEncoding:NSUTF8StringEncoding];
[newData writeToFile:saveFilePath options:NSDataWritingAtomic error:nil];
It reads the file, places it's contents into a variable called currentContents, then adds the new string to the file, and re-writes it. What's going wrong here.
Without the writeToFile line it works, with it, I get a crash.
Origin of saveFilePath
NSString *saveDocument = [NSString stringWithFormat:#"SavedFile.txt"];
NSString *docsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
saveFilePath = [docsDirectory stringByAppendingPathComponent:saveDocument];
An NSLog of saveFilePath reveals a correct path
I think your problem might actually be a missing null character ('\0') at the end of your NSData object. So you finally end up with messed up data. You might want to use -writeToFile:atomically:encoding:error: on your new string right away anyway.
It turns out that the reason the file wasn't writing was because of an unallocated variable:
NSString *currentContents = [NSString stringWithContentsOfFile:saveFilePath encoding:NSUTF8StringEncoding error:nil];
should have been:
NSString *currentContents = [[NSString alloc] initWithContentsOfFile:saveFilePath encoding:NSUTF8StringEncoding error:nil];

Objective-C / Can't access (read) file in "Resources" folder

This is probably a very easy problem to solve but i have not succeeded. I have copied the file "questions_famquiz_easy_110326.txt" to the resources folder and now want to access (read) it and NSLog it to see that i am able to read it.
The code below is from one of the tests i have done based on examples that i have found on the web.
I am trying to access a txt-file in the Resources folder and fail to do so. I have searched for a solution, tested a lot, but not succeeded.
I am testing with the following code:
NSLog(#"\n \n >>>>>>viewDidLoad<<<<<<<<<");
NSError *error;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *docsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [docsDirectory stringByAppendingPathComponent:#"questions_famquiz_easy_110326.txt"];
if(![fileManager fileExistsAtPath:filePath])
{
NSData *data = [NSData dataWithContentsOfFile:[[[NSBundle mainBundle] resourcePath] stringByAppendingString:#"/questions_famquiz_easy_110326.txt"]];
[data writeToFile:filePath atomically:YES];
}
NSString *myString = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:&error];
NSLog(#"myString: %#", myString);
NSLog(#"\n \n>>>>>>DONE WITH viewDidLoad<<<<<<<<<");
exit(0); //====EXIT JUST FOR THE TEST====<<<
The above code is located in the first viewController that is started.
The output i get is:
>>>>>>viewDidLoad<<<<<<<<<
2011-04-24 21:53:47.825 FamQuiz_R0_1[542:307] myString: (null)
2011-04-24 21:53:51.044 FamQuiz_R0_1[542:307]
>>>>>>DONE WITH viewDidLoad<<<<<<<<<
Could someone nice help me to solve this?
update:
Here is the filePath:
2011-04-24 22:38:08.562 FamQuiz_R0_1[637:307] filePath: /var/mobile/Applications/7F5FDB03-0D22-46BC-91BC-4D268EB4BBEB/FamQuiz_R0_1.app/questions_famquiz_easy_110326.txt
Here is where i have placed the file:
PROBLEM SOLVED:
NSString *myString = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:&error];
When i used the above it did not work, when i used the below it worked and printed out the text.
NSString *myString = [[NSString alloc] initWithContentsOfFile:filePath];
You're not reading from the resources folder. You're trying to read from the document directory. So getting back nil makes sense since the file doesn't exist there.
Change:
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *docsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [docsDirectory stringByAppendingPathComponent:#"questions_famquiz_easy_110326.txt"];
to:
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"questions_famquiz_easy_110326" ofType:#"txt"];
and it should work for you.

Rename file in Cocoa?

How would I rename a file, keeping the file in the same directory?
I have a string containing a full path to a file, and a string containing a the new filename (and no path), for example:
NSString *old_filepath = #"/Volumes/blah/myfilewithrubbishname.avi";
NSString *new_filename = #"My Correctly Named File.avi";
I know about NSFileManager's movePath:toPath:handler: method, but I cannot workout how to construct the new file's path..
Basically I'm looking for the equivalent to the following Python code:
>>> import os
>>> old_filepath = "/Volumes/blah/myfilewithrubbishname.avi"
>>> new_filename = "My Correctly Named File.avi"
>>> dirname = os.path.split(old_filepath)[0]
>>> new_filepath = os.path.join(dirname, new_filename)
>>> print new_filepath
/Volumes/blah/My Correctly Named File.avi
>>> os.rename(old_filepath, new_filepath)
NSFileManager and NSWorkspace both have file manipulation methods, but NSFileManager's - (BOOL)movePath:(NSString *)source toPath:(NSString *)destination handler:(id)handler is probably your best bet. Use NSString's path manipulation methods to get the file and folder names right. For example,
NSString *newPath = [[oldPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newFilename];
[[NSFileManager defaultManager] movePath:oldPath toPath:newPath handler:nil];
Both classes are explained pretty well in the docs, but leave a comment if there's anything you don't understand.
It's worth noting that moving a file to itself will fail. I had a method that replaced spaces with underscores and made the file name lowercase and renamed the file to the new name. Files with only one word in the name would fail the rename as the new name would be identical on a case-insensitive file system.
The way I resolved this was to do a two step rename, first renaming the file to a temporary name and then renaming it to the intended name.
Some pseudocode explaining this:
NSString *source = #"/FILE.txt";
NSString *newName = [[source lastPathComponent] lowercaseString];
NSString *target = [[oldPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newName];
[[NSFileManager defaultManager] movePath:source toPath:target error:nil]; // <-- FAILS
The solution:
NSString *source = #"/FILE.txt";
NSString *newName = [[source lastPathComponent] lowercaseString];
NSString *temp = [[oldPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:[NSString stringWithFormat:#"%#-temp", newName]];
NSString *target = [[oldPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newName];
[[NSFileManager defaultManager] movePath:source toPath:temp error:nil];
[[NSFileManager defaultManager] movePath:temp toPath:target error:nil];
I just wanted to make this easier to understand for a newbie. Here's all the code:
NSString *oldPath = #"/Users/brock/Desktop/OriginalFile.png";
NSString *newFilename = #"NewFileName.png";
NSString *newPath = [[oldPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newFilename];
[[NSFileManager defaultManager] movePath:oldPath toPath:newPath handler:nil];
NSLog( #"File renamed to %#", newFilename );
here's a more recent example for iOS, the NSFileManager method is a little different:
NSString *newFilename = [NSString stringWithFormat:#"%#.m4a", newRecording.title];
NSString *newPath = [[newRecording.localPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newFilename];
[[NSFileManager defaultManager] moveItemAtPath:newRecording.localPath toPath:newPath error:nil];
For the icing on top, a category on NSFileManager:
#implementation NSFileManager (FileManipulations)
- (void)changeFileNamesInDirectory:(NSString *)directory changeBlock:(NSString * (^) (NSString *fileName))block
{
NSString *inputDirectory = directory;
NSFileManager *fileManager = [NSFileManager new];
NSArray *fileNames = [fileManager contentsOfDirectoryAtPath:inputDirectory error:nil];
for (NSString *fileName in fileNames) {
NSString *newFileName = block(fileName);
NSString *oldPath = [NSString stringWithFormat:#"%#/%#", inputDirectory, oldFileName];
// move to temp path so case changes can happen
NSString *tempPath = [NSString stringWithFormat:#"%#-tempName", oldPath];
NSString *newPath = [[oldPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newFileName];
NSError *error = nil;
[fileManager moveItemAtPath:oldPath toPath:tempPath error:&error];
if (error) {
NSLog(#"%#", [error localizedDescription]);
return;
}
[fileManager moveItemAtPath:tempPath toPath:newPath error:&error];
if (error) {
NSLog(#"%#", [error localizedDescription]);
}
}
}
#end