How to write a file in IOS - objective-c

I am new to IOS programming. I want to write some data into file. I have opened successfully the file in Document path. But fwrite its not working as expected. If I open the file its empty. Its my code I'm using. What I'm doing wrong.
typedef struct test {
int a;
} TEST_OBJ;
TEST_OBJ test_obj1;
test_obj1.a = 5;
TEST_OBJ *data_ptr = &test_obj1;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *appFile = [documentsDirectory stringByAppendingPathComponent:#"MyFile1.txt"];
//This is working fine.
// [data writeToFile:appFile atomically:YES];
NSFileManager *fileManager = [[NSFileManager alloc]init];
char const *path = [fileManager fileSystemRepresentationWithPath:appFile];
FILE *fp = fopen(path, "w+b");
// This write is not working. File is empty.
int cnt = fwrite (data_ptr , 1 , sizeof(test_obj1) , fp );
fclose(fp);
fp = NULL;
Anyone pls tell me what I'm doing wrong?

I recommend you use NSData instead of C functions.
NSData *myData = [[NSData alloc] initWithBytes:bytes length:length];
[myData writeToFile:path atomically:YES];

you can use NSData,NSArray,NSDictionary,they have [writeToFile: atomically:] method ,it can write the data into the file.
if you must C to read and write filestream,you can use my method below , it can add arrayString to the file .
- (void)putArrayString:(NSString *)arrayString toFilePath:(NSString *)filePath
{
FILE *fileStream = fopen([filePath UTF8String], "a+");
if(fileStream == NULL)
{
fclose(fileStream);
fileStream = fopen([filePath UTF8String], "w+");
fputs([arrayString UTF8String], fileStream);
}
else
{
fputs([arrayString UTF8String], fileStream);
}
fclose(fileStream);
}

I have changed the mode of opening a+ its writing and reading properly now. Thanks all for your help.

See if you can use this code:
https://github.com/RIKSOF/three20/blob/master/src/extThree20RemoteObject/Source/TTObjectModel.m
Start reading from the encodeToDocument method. It writes all properties of an object in to a JSON or XML file.
Any subclass of this class having any property is properly written back.

Related

writeToFile does not work after removeItemAtPath

I have an iOS app that at times needs to store UIImage objects locally.
I am using [UIImagePNGRepresentation(image) writeToFile:full_path options:NSAtomicWrite error:nil]; to save the image and [file_manager removeItemAtPath:full_path error:NULL]; to delete the file.
This all works great, however, whenever I delete a file, should I decide to save a new file (which just so happens to have the same name as the old file), the save code doesn't work and returns the following error:
: ImageIO: CGImageReadCreateDataWithMappedFile 'open' failed
error = 2 (No such file or directory)
: ImageIO: CGImageReadCreateDataWithMappedFile 'open' failed
error = 2 (No such file or directory)
: ImageIO: PNG zlib error
So heres what I don't get, why can't I save a file with the same name as the old file, after I have deleted the old file?
The reason I ask this, is that, my app will save certain image files and then when they are no longer needed, my app will delete them. However, there are times when my app needs the image files again (could be a few hours after deletion or a few weeks). When this happens, my app will load the appropriate image data and then try to save it. And thats when the error occurs.
Whats going wrong here?
Thanks for your time, Dan.
UPDATE - Here are the methods I have setup to save/access and delete my image files
-(void)save_local_image:(UIImage *)image :(NSString *)file_name {
// Get the app documents directory link.
NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
// Add the new file name to the link.
NSString *database_link = [[NSString alloc] initWithString:[documents stringByAppendingPathComponent:file_name]];
// Save the image data locally.
[UIImagePNGRepresentation(image) writeToFile:database_link options:NSAtomicWrite error:nil];
}
-(UIImage *)get_local_image:(NSString *)file_name {
// Create the return data.
UIImage *image_data = nil;
// Get the app documents directory.
NSArray *directory = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] error:NULL];
// Only check for data if at least
// one file has been saved locally.
if ([directory count] > 0) {
// Loop through the different local files.
for (NSString *path in directory) {
// Get the full local file URL.
NSString *full_path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:path];
// Get the range of the file name.
NSRange range = [full_path rangeOfString:file_name];
// Get the image data if it exists.
if ((range.location != NSNotFound) || (range.length == [file_name length])) {
// Load the image file in.
image_data = [UIImage imageWithContentsOfFile:full_path];
break;
}
}
}
return image_data;
}
-(void)delete_local_image:(NSString *)file_name {
// Get the app documents directory.
NSArray *directory = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] error:NULL];
// Only check for data if at least
// one file has been saved locally.
if ([directory count] > 0) {
// Loop through the different local files.
for (NSString *path in directory) {
// Get the full local file URL.
NSString *full_path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:path];
// Get the range of the file name.
NSRange range = [full_path rangeOfString:file_name];
// Delete the local image data if it exists.
if ((range.location != NSNotFound) || (range.length == [file_name length])) {
NSError *testError = nil;
// Delete the image file.
NSFileManager *file_manager = [[NSFileManager alloc] init];
BOOL success = [file_manager removeItemAtPath:full_path error:&testError];
NSLog(#"%d", success);
if (testError != nil) {
NSLog(#"%#", testError.localizedDescription);
}
break;
}
}
}
}
I am using this to save and read:
- (void) saveImageToFile:(NSString *) urlImg withNameNumber:(int)numberName andQuestionId:(int) questionID
{
NSString* documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString* foofile = [documentsPath stringByAppendingPathComponent:[NSString stringWithFormat:#"gallery%d%d.jpg",numberName,questionID]];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:foofile];
if (!fileExists) {
NSData *tempImgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#%#",#"https://testurl/",urlImg]]];
NSString *filename = [NSString stringWithFormat:#"gallery%d%d.jpg",numberName,questionID];
NSString *imagePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:filename];
[tempImgData writeToFile:imagePath atomically:YES];
}
}
-(UIImage*) readImageFromFile:(int)numberName andQuestionId:(int) questionID
{
NSString * documentsDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
return [UIImage imageWithContentsOfFile:[NSString stringWithFormat:#"%#/gallery%d%d.jpg",documentsDirectoryPath,numberName,questionID]];
}

How to save mixed file with AVAudioUnit without playing?

At now I save file by recording it from AVAudioUnitEQ.
[mainEQ installTapOnBus:0 bufferSize:0 format:[mainEQ outputFormatForBus:0] block:^(AVAudioPCMBuffer *buf, AVAudioTime *when){
if(!recordIsGoing){
[mainEQ removeTapOnBus:0];
}
else{
[writeAudioFile writeFromBuffer:buf error:nil];
// NSLog(#"%lld", writeAudioFile.length);
}
}];
But this method requires a prior file playback . Is there a way to save the mixed file without playing ?
UPD: I can get AUAudioUnit.outputBusses[0] to mainEQ.
The challenge now is to take out the data and hope that they will be such what I need.
RESOLVED: Issue been resolved by this answer Can I use AVAudioEngine to read from a file, process with an audio unit and write to a file, faster than real-time?
I think you can do this by first converting your data into NSData and storing it. When you retrieve it back, you can convert it back.
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:buf];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:#"yourfilename.dat"];
// Save it into file system
[data writeToFile:dataPath atomically:YES];

Read from file.Plist Returns Null

Program that Creates multiple Plist's Paths for Different information.
But only one path is not working.
(i think "writeToFile" is the problem)
code:
-(NSString *) createPath:(NSString *)withFileName
{
NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,
YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:withFileName];
return path;
}
Path
NSLog = /var/mobile/Applications/02CABC0A-6B5B-4097-A9D1-4336BE8230B7/Documents/MessagesDB.plist
&
-(void) messagesDbFlush
{
// save it to the file for persistency
NSString *messagesDB_Path = [self createPath:_fileMessagesDB];
[_messagesDB writeToFile:messagesDB_Path atomically:YES];
NSMutableArray *ReturnsInfo = [[NSMutableArray alloc ]initWithContentsOfFile:messagesDB_Path];
NSLog(#"ReturnsInfo is : %#", ReturnsInfo);
}
"ReturnsInfo" Array is Null :/
Anyone please help?
I once had the same error.
1) Check the name of the plist in the directory listing to match your coded one
2) Check Project settings, manually delete the pre-existing plist from the "Build Settings" > "Copy Bundle Resources", and drag drop from the list.
3) Select the plist in directory listing, check Utilities sidebar, check Identity & Type > Location as valid
4) If you deleted the app's "default" plist aka bundle identifier, add copy build phase, choose destination, choose pref folder as absolut path check "copy only when installing"
This solved my returning null.
And if all fails on the bundle identifier, you can always copy the plist to pref folder by code:
NSString *path = [#"~/Library/Preferences/com.MyCompany.MyApp.plist" stringByExpandingTildeInPath];
BOOL PrefsExist=[[NSFileManager defaultManager] fileExistsAtPath:path];
NSString *copyPrefsPath = [#"~/Library/Preferences/com.MyCompany.MyApp.plist" stringByExpandingTildeInPath];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (PrefsExist == 0)
{
// Copy the plist to prefs folder (one-time event)
NSString *tessdataPath = [[NSBundle mainBundle] pathForResource:#"com.MyCompany.MyApp" ofType:#"plist"];
[fileManager copyItemAtPath:tessdataPath toPath:path error:&error];
} else
{
// Read/Write the values from plist
}
i have stored following array with 5 objects in it, its working fine on my side, try it
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:5];
for(int i=0;i<5;i++)
[array addObject:#"This is Demo String, You can write your own String here"];
NSString *_fileMessagesDB = #"MessagesDB.plist";
// save it to the file for persistency
NSString *messagesDB_Path = [self createPath:_fileMessagesDB];
[array writeToFile:messagesDB_Path atomically:YES];
NSMutableArray *ReturnsInfo = [[NSMutableArray alloc ]initWithContentsOfFile:messagesDB_Path];
NSLog(#"ReturnsInfo is : %#", ReturnsInfo);

How to close a file in Objective-C

I´m trying to store some data in a file. I open the file the first iteration, and add the info. But, when the algorithm end, file size is 5kbs, it must be like 2,5 Mbs.
if (!isopen)
{
NSArray *paths;
paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
// Check DD
if ([paths count] > 0)
{
NSLog(#"Found a path");
fichero2 = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"out2.raw"];
NSLog(#"path %#",fichero2);
} else {
//d'oh, something went really wrong
NSLog(#"ERROR: could not open %s\n", "out.raw");
return -1;
}
isopen = 1;
}
else
{
// Write file
NSMutableData *data = [NSMutableData dataWithLength:1152*2];
[data appendBytes:((SInt16 *)[audioProcessor audioBuffer].mData) length:1152*2];
[data writeToFile:fichero2 atomically:YES];
}
Is really need to close the file? It auto close itself? So, why data is not stored?
I think you are creating a new NSData each loop,
Should be outside the dope of the iteration, no?
NSMutableData *data = [NSMutableData dataWithLength:1152*2];
then for
[data appendBytes:((SInt16 *)[audioProcessor audioBuffer].mData) length:1152*2];
[data writeToFile:fichero2 atomically:YES];

Appending NSString while using NSApplicationSupportDirectory to create a new directory

I have been trying to create a new file inside of my application support folder while using NSApplicationSupportDirectory; I can write a file to it, but I have been unable to create a folder inside of Application Support.
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSApplicationSupportDirectory, NSUserDomainMask, YES);
NSString *applicationDirectory = [paths objectAtIndex:0];
//make a file name to write the data to using the application support: (attempting to create the blasted directory inside of application support directory
NSString *fileName = [NSString stringWithFormat:#"%#/managersemail.txt",
applicationDirectory];
//create content - formats with the managersemail.txt location
NSString* content = [NSString stringWithFormat:#"%#",[nameField stringValue]];
//save content to the documents directory
[content writeToFile:fileName
atomically:NO
encoding:NSStringEncodingConversionAllowLossy
error:nil];
NSDictionary* errorDict;
The code that I have listed above works great, except for the part about creating the folder in which I want to place the managersemail.txt. I tried to mimic the stringWithFormat that is listed in the NSString* content and then varying several ways however to no avail! Any thoughts?
NSAppleEventDescriptor* returnDescriptor = NULL;
Perhaps the solution provided on Cocoa with Love might be useful?
Excerpt:
- (NSString *)findOrCreateDirectory:(NSSearchPathDirectory)searchPathDirectory
inDomain:(NSSearchPathDomainMask)domainMask
appendPathComponent:(NSString *)appendComponent
error:(NSError **)errorOut
{
// Search for the path
NSArray* paths = NSSearchPathForDirectoriesInDomains(
searchPathDirectory,
domainMask,
YES);
if ([paths count] == 0)
{
// *** creation and return of error object omitted for space
return nil;
}
// Normally only need the first path
NSString *resolvedPath = [paths objectAtIndex:0];
if (appendComponent)
{
resolvedPath = [resolvedPath
stringByAppendingPathComponent:appendComponent];
}
// Check if the path exists
BOOL exists;
BOOL isDirectory;
exists = [self
fileExistsAtPath:resolvedPath
isDirectory:&isDirectory];
if (!exists || !isDirectory)
{
if (exists)
{
// *** creation and return of error object omitted for space
return nil;
}
// Create the path if it doesn't exist
NSError *error;
BOOL success = [self
createDirectoryAtPath:resolvedPath
withIntermediateDirectories:YES
attributes:nil
error:&error];
if (!success)
{
if (errorOut)
{
*errorOut = error;
}
return nil;
}
}
if (errorOut)
{
*errorOut = nil;
}
return resolvedPath;
}
Maybe you can try using the NSFileManager to create the folder, then write the file into the folder.
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *applicationSupport = [[NSString stringWithString:#"~/Library/Application Support/'YOUR APP'] stringByExpandingTildeInPath];
if ([fileManager fileExistsAtPath:applicationSupport] == NO)
[fileManager createDirectoryAtPath:applicationSupport withIntermediateDirectories:YES attributes:nil error:nil];
NSString *fileName = [NSString stringWithFormat:#"%#/managersemail.txt", applicationSupport];
NSString* content = [NSString stringWithFormat:#"%#",[nameField stringValue]];
//save content to the documents directory
[content writeToFile:fileName
atomically:NO
encoding:NSStringEncodingConversionAllowLossy
error:nil];
So something like that should work. Feel free to leave comments to ask questions.