File read using contentsAtPath not working - objective-c

The following is my code and I have the newfile2 in the same directory as main.m is located(see image) but I am getting File read failed error. Where am I going wrong?
import
int main(int argc, const char * argv[])
{
#autoreleasepool {
NSFileManager *fm;
NSData *fileData;
fm = [NSFileManager defaultManager];
//Read from the file nwefile2
fileData = [fm contentsAtPath:#"newfile2"];
if (fileData == nil) {
NSLog(#"File read failed");
return 1;
}
//Write the data to a file
if ([fm createFileAtPath:#"newfile3" contents:fileData attributes:nil] == NO) {
NSLog(#"File creation failed");
return 2;
}
NSLog(#"File copy successful");
}
return 0;
}

The problem is that this line doesn't say where to find the file:
fileData = [fm contentsAtPath:#"newfile2"];
You are assuming that a partial path will find the file (perhaps because you think the working directory is the same directory as your program?), but that is a false assumption. Nothing is known about what the working directory is! You have to be specific about where the file is.

The correct way to specify the path in-spite of hardcoding the path is use below api of NSBundle class:-
- (NSString *)pathForResource:(NSString *)name ofType:(NSString *)extension
Write like that below:-
fileData = [fm contentsAtPath:[[NSBundle mainBundle]
pathForResource:#"newfile2" ofType:#"fileExt"]];
Note:- Before fetching the file path, your file should be present in the resource directory,.

Related

Unable to delete the contents of a Directory in my Home Directory using NSDirectoryEnumerator

I have been unable to delete the contents of a directory using NSDirectoryEnumerator.
Here is my method:
- (BOOL) deleteDirectoryContents:(NSString *)directoryPath
{
BOOL success = FALSE;
BOOL isDir;
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:directoryPath isDirectory:&isDir] && isDir)
{
NSDirectoryEnumerator *dirEnum = [fileManager enumeratorAtPath:directoryPath];
NSLog(#"dirEnum in deleteDirectoryContents is %#", dirEnum);
NSString *documentsName;
// NSLog(#"[dirEnum nextObject] is: %#", [dirEnum nextObject]);
while (documentsName = [dirEnum nextObject])
{
NSString *filePath = [directoryPath stringByAppendingString:documentsName];
NSLog(#"filePath is: %#", filePath);
BOOL isFileDeleted = [fileManager removeItemAtPath:filePath error:nil];
if(isFileDeleted == NO)
{
NSLog(#"All Contents not removed");
success = FALSE;
break;
}
success = TRUE;
}
if (success) NSLog(#"All Contents Removed");
}
return success;
}
And this is my code in my main program:
NSString *testDir = #"/Users/grinch/MyTestTemp";
//testDir = [NSHomeDirectory() stringByAppendingPathComponent: #"MyTestTemp"];
NSLog(#"testDir is: %#", testDir);
BOOL result = [self deleteDirectoryContents:testDir];
NSLog(#"result is: %d", result);
Here is my console output:
testDir is: /Users/grinch/MyTestTemp
dirEnum in deleteDirectoryContents is <NSAllDescendantPathsEnumerator: 0x60000008c300>
result is: 0
I also checked the value of [dirEnum nextObject] (by uncommenting the NSLog statement in my code). It returns null. And I never see the "filePath is" NSLog statement. So the inner while loop is NEVER executed.
And yes the directory (with files) does exist in my home directory. I created these files. I have permissions. I can easily delete the files in this directory using Finder
What am I missing?
P.S. I did some more testing. It looks like my simple program in Xcode does not have permissions to access files and folders in my home directory. Why? I have no idea.
Here is my additional test code:
NSError *errorMsg;
[[NSFileManager defaultManager] removeItemAtPath:#"/Users/grinch/myTestTemp/Hello.txt" error:&errorMsg];
if (errorMsg) NSLog(#"ERROR - File delete errorMsg is: %#", errorMsg);
success = [[NSFileManager defaultManager] removeItemAtPath:testDir error:&errorMsg];
if (errorMsg) NSLog(#"ERROR - Folder delete errorMsg is: %#", errorMsg);}
And here is my console output:
2022-09-10 09:56:48.958352-0400 NSAlert[97106:7511815] ERROR - File delete errorMsg is: Error Domain=NSCocoaErrorDomain Code=513 "“Hello.txt” couldn’t be removed because you don’t have permission to access it." UserInfo={NSFilePath=/Users/grinch/myTestTemp/Hello.txt, NSUserStringVariant=(
), NSUnderlyingError=0x6040006421f0 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}
2022-09-10 09:56:48.960560-0400 NSAlert[97106:7511815] ERROR - Folder delete errorMsg is: Error Domain=NSCocoaErrorDomain Code=513 "“MyTestTemp” couldn’t be removed because you don’t have permission to access it." UserInfo={NSFilePath=/Users/grinch/MyTestTemp, NSUserStringVariant=(
), NSUnderlyingError=0x60400045ff80 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}
So my questions are:
Why didn't the directory enumerator work?
Why doesn't Xcode have the permissions to delete items in my home folder?
How can I give Xcode the the ability (or permissions) to delete items in my home directory?
I have found a bug in my deleteDirectoryContents: method above. And as a result, have answered most of my questions!
First, the statement NSString *filePath = [directoryPath stringByAppendingString:documentsName]; in the while loop will not work. One must insert a / before documentsname. So the line should be NSString *filePath = [directoryPath stringByAppendingFormat:#"/%#",documentsName]; OR even better use NSString *filePath = [directoryPath stringByAppendingPathComponent:documentsName];.
Now the method deleteDirectoryContents: will work as expected.
Here is the code to the fixed method:
- (BOOL) deleteDirectoryContents:(NSString *)directoryPath
{
BOOL success = FALSE;
BOOL isDir;
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:directoryPath isDirectory:&isDir] && isDir)
{
NSDirectoryEnumerator *dirEnum = [fileManager enumeratorAtPath:directoryPath];
NSLog(#"dirEnum in deleteDirectoryContents is %#", dirEnum);
NSString *documentsName;
// NSLog(#"[dirEnum nextObject] is: %#", [dirEnum nextObject]);
while (documentsName = [dirEnum nextObject])
{
//NSString *filePath = [directoryPath stringByAppendingFormat:#"/%#",documentsName];
NSString *filePath = [directoryPath stringByAppendingPathComponent:documentsName];
NSLog(#"filePath is: %#", filePath);
NSError *errorMsg = nil;
BOOL isFileDeleted = [fileManager removeItemAtPath:filePath error:&errorMsg];
if (errorMsg) NSLog(#"ERROR - Failed to delete file or folder at: %#. Error message is: %#", filePath, errorMsg);
if(isFileDeleted == NO)
{
NSLog(#"All Contents not removed");
success = FALSE;
break;
}
success = TRUE;
}
if (success) NSLog(#"All Contents Removed");
}
return success;
}
And I can confirm that if your program creates the directory and the files within it, the program can also delete these files using deleteDirectoryContents: while running in the Xcode sandbox DEPENDING on where the folder was originally created.
If the program creates the folder and files in a temporary directory (e.g. caches directory) NOT the users home folder, it works.
But due to Xcode sandboxing,
deleteDirectoryContents: does not appear to work on folder and files created by the program in the users Home directory when running within Xcode.
P.S. I used the following to obtain a temporary directory name:
- (NSString *) get_temporary_dir
{
NSString *path = nil;
NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleIdentifier"];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
if ([paths count]) {
path = [[paths objectAtIndex:0] stringByAppendingPathComponent:bundleName];
} else {
path = NSTemporaryDirectory();
path = [path stringByAppendingPathComponent:bundleName];
}
return [[[NSString alloc] initWithUTF8String:[path UTF8String]] autorelease];
}
Then the program created the temporary directory using that name. The program created some files in that temporary directory and then was able to delete them using the deleteDirectoryContents: method above.

What happens to the Users/username/Library directory. Why can't I change the current directory?

I was following a code sample from "Programming in Objective-C Fourth Edition" by Stephen Kochan.
The program looks for a file, and performs a few things on it:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
#autoreleasepool {
NSString *fName = #"testfile";
NSFileManager *fm;
NSDictionary *attr;
//Need to create an instance of the file manager
fm = [NSFileManager defaultManager];
//Let's make sure our test file exists first
NSLog([fm currentDirectoryPath]);
if ([fm fileExistsAtPath: fName] == NO) {
NSLog(#"File doesn't exist!");
return 1;
}
//now lets make a copy
if ([fm copyItemAtPath: fName toPath: #"newfile" error: NULL]) {
NSLog(#"File Copy failed!");
return 2;
}
//Now let's see test to see if the two files are equal
if ([fm contentsEqualAtPath: fName andPath: #"newfile"] == NO) {
NSLog(#"Files are Not Equal!");
return 3;
}
//Now lets rename the copy
if ([fm moveItemAtPath: #"newfile" toPath: #"newfile2" error: NULL] == NO) {
NSLog(#"File rename Failed");
return 4;
}
//get the size of the newfile2
if((attr = [fm attributesOfItemAtPath: #"newfile2" error: NULL]) == nil)
{
NSLog(#"Couldn't get file attributes");
return 5;
}
NSLog(#"File size is %llu bytes", [[attr objectForKey: NSFileSize] unsignedLongLongValue]);
//And finally, let's delete the original file
if([fm removeItemAtPath: fName error: NULL])
{
NSLog(#"file removal failed");
return 6;
}
NSLog(#"All operations were successful");
//Display the contents of the newly-createed file
NSLog(#" %#", [NSString stringWithContentsOfFile: #"newfile2" encoding:NSUTF8StringEncoding error: NULL]);
}
return 0;
}
I created a file named "testfile" and placed it in project directory. When I ran the program, It couldn't find the file. I added [NSFileManager currentDirectoryPath] to check the current path which was apparently something like this:
/Users/myusername/Library/Developer/Xcode/DerivedData/Prog_16.1-eekphhgfzdjviqauolqexkowfqfg/Build/Products/Debug
I went looking for the Library directory, but it doesn't exist. Is this some temporary directory that's created when the program is running, then deleted after it exits?
Edit: I've tried changing the path of the current directory using [NSFileManager changeCurrentDirectoryPath: newPath] and it fails to change the path. I tried setting to newPath to #"Users/username/Desktop" and that fails too!
The Library directory does exist but it is hidden as standard. Open up the terminal and type the command: chflags nohidden ~/Library/.
Then look again and it will be magically there!
Edit: for programming with NSFileManager there's a very useful function: NSSearchPathForDirectoriesInDomains(). E.g. To get the desktop do directory:
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDesktopDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:#"test.txt"];
NSString *test = #"hello";
[test writeToFile:path atomicallly:YES];
This will write a little txt file to your desktop. (As long as you app isn't sandboxed).
Hope this helps.
When you place a file in the project directory, it gets shipped as part of the app's bundle. To get at the bundle directory tree, use NSBundle...
// use the file extension (if any) for the ofType: param
NSString *path = [[NSBundle mainBundle] pathForResource:#"testfile" ofType:#""];
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
NSLog(#"there it is! %#", path);
}

Can't move a file in objective c

I'm a beginner in this language.
I want to move a file from one folder to another my code is here.
The console give me file exists at path twice
And the moveItemAtPath gives me always false
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
#autoreleasepool {
NSString * originPath = [NSHomeDirectory() stringByAppendingPathComponent:#"Downloads/1.wav"];
NSString * finalPath = [NSHomeDirectory() stringByAppendingPathComponent:#"Desktop"];
NSFileManager * manager = [[NSFileManager alloc]init];
if( [ manager fileExistsAtPath:originPath]){
NSLog(#"The file exists at: %#",originPath);
}
if( [manager fileExistsAtPath:finalPath]){
NSLog(#"The file exists at: %#",finalPath);
}
if([manager moveItemAtPath:originPath toPath:finalPath error:nil]){
NSLog(#"True");
}else{
NSLog(#"FALSE");
}
}
return 0;
}
First of all you should use [NSFileManager defaultManager] instead of creating a new NSFileManager. It will return a singleton-instance of NSFileManager.
Add this to your second "ifFileExists"-check:
[[NSFileManager defaultManager] removeItemAtPath:finalPath error:nil];
This will remove the item at the target-path, before moving a new one to this destination.

How do I find a file that I am trying to unzip using ZipArchive?

ZipArchive is not able to locate the file that I am trying to unzip. What am I doing wrong? I am trying to do all of this in dispatch_async, is that my problem?
I end up with "Could not find zip file." in my log. And when I check look for the directory that should have been created in my app data file, it is nowhere to be found. How ever the zip file is there.
Here is a link to a tutorial that closely resembles what I am trying to do. I have also added the libraries needed.
Code Edited Per Request to include error handling:
NSLog(#"Got the data!");
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *path = [paths objectAtIndex:0];
//Save the data
NSLog(#"Saving");
NSString *dataPath = [path stringByAppendingPathComponent:#"TKAPlacesImages.zip"];
dataPath = [dataPath stringByStandardizingPath];
NSError *error = nil;
[urlData writeToFile:dataPath options:0 error:&error];
if(!error)
{
if (![defaults objectForKey:#"places images path"]) {
[defaults setObject:path forKey:#"places images path"];
[defaults synchronize];
}
ZipArchive* za = [[ZipArchive alloc] init];
if( [za UnzipOpenFile:dataPath] )
{
BOOL ret = [za UnzipFileTo:path overWrite: YES];
if (NO == ret){} [za UnzipCloseFile];
NSLog(#"Successful unzip of: %#",#"/Library/Caches/TKAPlacesImages.zip");
}
else
{
NSLog(#"Could not find zip file.");
}
}
else
{
NSLog(#"Error saving file %#",error);
}
PHP Code Added
function zip_image_files($images) {
// Prepare File
$file = tempnam("tmp", "zip");
$zip = new ZipArchive();
$zip->open($file, ZipArchive::OVERWRITE);
$imagesCount = count($images);
$imagesString = '';
for($i=0; $i < $imagesCount; $i++)
{
// Stuff with content
$imagesString = ".." . $images[$i];
if(file_exists($imagesString))
{
$zip->addFile($imagesString);
}
else
{
echo $imagesString;
}
}//end for
// Close and send to users
$zip->close();
header('Content-Type: application/zip');
header('Content-Length: ' . filesize($file));
header('Content-Disposition: attachment; filename="file.zip"');
readfile($file);
unlink($file);
}
//end function
Edit
My function returns a 19.2MB zip file. However in my app data file the zip file is 0 bytes.
I'm betting that either (1) urlData is nil and so nothing is being written because there is nothing to write or (2) urlData is not zipped data and to unzip it is failing. Chances are that the first one is the actual issue, since you say you don't see any written file.

Objective C - Create text file to read and write line by line in Cocoa

I building a Mac app,I have 2 problem:
I want to create a text file to read and write data on it. I don't know how to crate a text file to read and write data. Is it use
struct?
I want to create a XML file to read and write data on it. Can I create a struct for XML?
Do you have suggestion? Thanks in advance
Well, to create a file, just use
[[NSFileManager defaultManager] createFileAtPath:#"Your/Path" contents:nil attributes:nil];
This creates an empty file, which you can write to or read from. To write text (or XML), just use NSString's writeToFile:atomically:encoding:error: method like this
NSString *str = //Your text or XML
[str writeToFile:"Your/Path" atomically:YES encoding:NSUTF8StringEncoding error:nil];
To read from a file, just make an NSString with the contents of that file
NSString *contents = [NSString stringWithContentsOfFile:#"Your/Path"];
or, if it does not contain a string, get an NSData object from the file
NSData *contents = [NSData dataWithContentsOfFile:#"Your/Path"];
/**************************main.m******************************
NS FILE HANDLE READ & WRITE
reading and writing in same file
Created by abdulsathar on 6/16/14.
***************************************************************/
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
#autoreleasepool //ARC
{
NSFileHandle *file;
//object for File Handle
NSError *error;
//crearing error object for string with file contents format
NSMutableData *writingdatatofile;
//create mutable object for ns data
NSString *filePath=[NSString stringWithFormat:#"/Users/chandrakumar/Documents/abdul/doc.txt"];
//telling about File Path for Reading for easy of access
file = [NSFileHandle fileHandleForReadingAtPath:#"/Users/chandrakumar/Documents/abdul/doc.txt"];
//assign file path directory
if (file == nil) //check file exist or not
NSLog(#"Failed to open file");
NSString *getfileContents = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:&error];
//access file contents with out ns handle method
if (error) //check error flag for file present or not
NSLog(#"Error reading file: %#", error.localizedDescription);
NSLog(#"contents: %#", getfileContents);
//display file contents in main file
NSArray *listArray = [getfileContents componentsSeparatedByString:#"\n"];
//caluculate list of line present in files
NSLog(#"items = %ld", [listArray count]);
const char *writingchar = "how are you";
writingdatatofile = [NSMutableData dataWithBytes:writingchar length:strlen(writingchar)];
//convert string format into ns mutable data format
file = [NSFileHandle fileHandleForUpdatingAtPath: #"/Users/chandrakumar/Documents/abdul/new.txt"];
//set writing path to file
if (file == nil) //check file present or not in file
NSLog(#"Failed to open file");
[file seekToFileOffset: 6];
//object pointer initialy points the offset as 6 position in file
[file writeData: writingdatatofile];
//writing data to new file
[file closeFile];
//close the file
}
return 0;`enter code here`
}
/***********************************OUTPUT********************************************
2014-06-17 14:55:39.695 storage[4075:303] contents: hello how are you my dearservice
*************************************************************************************/