i am new to iPhone programming.
What is the proper way to check that whether a file is exist or not?
BOOL isDirectory = NO;
if ( [[NSFileManager defaultManager]
fileExistsAtPath:path
isDirectory: &isDirectory ]) {
// file already exists
} else {
// file does not yet exist
}
To put it in more detail:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
if ([[NSFileManager defaultManager] fileExistsAtPath:documentsDirectory]){
//Do something...
}
You can append the actual file name to "documentsDirectory" like this: [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.jpg", spidermanpic]].
The isDirectory option in the answer above is used to check if the path is a directory or a file. Please keep in mind that it is a pointer. It wont work without the "&".
Related
This could be easy, but I am not getting the problem.
I am using below code to rename the folders of document directory and is working fine except one case.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:#"Photos"];
NSArray * arrAllItems = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:dataPath error:NULL]; // List of all items
NSString *filePath = [dataPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%#", [arrAllItems objectAtIndex:tagSelected]]];
NSString *newDirectoryName = txtAlbumName.text; // Name entered by user
NSString *oldPath = filePath;
NSString *newPath = [[oldPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newDirectoryName];
NSError *error = nil;
[[NSFileManager defaultManager] moveItemAtPath:oldPath toPath:newPath error:&error];
if (error) {
NSLog(#"%#",error.localizedDescription);
// handle error
}
Now, my problem is if there is a folder named "A"(capital letter A) and I am renaming it to "a" (small letter a), then it is not working and giving an error. I am not getting where the problem is.
The HFS+ file system (on OS X) is case insensitive, but case preserving.
That means if you create a folder "A" and then check if there is a folder "a", you will get
"yes" as an answer.
The file manager moveItemAtPath:toPath:... checks first if the destination path already
exists and therefore fails with
NSUnderlyingError=0x7126dc0 "The operation couldn’t be completed. File exists"
One workaround would be to rename the directory to some completely different name first:
A --> temporary name --> a
But a much easier solution is to use the BSD rename() system call, because that
can rename "A" to "a" without problem:
if (rename([oldPath fileSystemRepresentation], [newPath fileSystemRepresentation]) == -1) {
NSLog(#"%s",strerror(errno));
}
Note that the problem occurs only on the iOS Simulator, not on the device, because
the device file system is case sensitive.
Swift:
let result = oldURL.withUnsafeFileSystemRepresentation { oldPath in
newURL.withUnsafeFileSystemRepresentation { newPath in
rename(oldPath, newPath)
}
}
if result != 0 {
NSLog("%s", strerror(errno))
}
I have a strange problem, this code check if a file exist inside document folder:
- (BOOL) checkIfFileExist:(NSString *)path {
NSArray *documentsPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [documentsPaths objectAtIndex:0];
NSString *fileDaControllere = [documentsDirectory stringByAppendingString:path];
if ([[NSFileManager defaultManager] fileExistsAtPath:fileDaControllere]) {
NSLog(#"exist");
return YES;
}
else {
NSLog(#"not exist");
return NO;
}
}
the problem is that I get alway file not exist while the file exist (in this case the path is Style.css)! where is the mistake?
The path seems to be correct:
Path: /Users/kikko/Library/Application Support/iPhone Simulator/6.0/Applications/38161AFA-2740-4BE2-9EC4-C5C6B317D270/Documents/Style.css
Here you can see the path on xcode and real path
http://www.allmyapp.net/wp-content/iFormulario/1.png
http://www.allmyapp.net/wp-content/iFormulario/2.png
The problem may be in the fact that you just append the file without with check if there is a path delimitor:
NSString *fileDaControllere = [documentsDirectory stringByAppendingString:path];
Thus you would become something like ../DocumentsStyle.css but it should be ../Documents/Style.css.
NSString has a special method for appending path components stringByAppendingPathComponent:
NSString *fileDaControllere = [documentsDirectory stringByAppendingPathComponent:path];
At the end I solved this issue, the strange think is that I don't know how I solved it,
the first problem is that I pass to checkIfFifFileExist the absolute path while I need to pass it relative path, and the the function trasform it to absolute path (my big big error), after this I think the problem is the use of "/", I delete all and rewrite all the code and I doing some test.
I copy folder from bundle:
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
NSString *folderPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"/icone"];
NSString *iconePath = [documentsDir stringByAppendingPathComponent:#"/icone"];
[[NSFileManager defaultManager] copyItemAtPath:folderPath toPath:iconePath error:nil];
Then I make the path of my image in this way:
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
NSString *imagePath = [documentsDir stringByAppendingPathComponent:self.objMateria.iconaMateria];
and now the file exist, a strange thing is that if:
self.objMateria.iconaMateria = /icona/Home/fisica.png
or
self.objMateria.iconaMateria = icona/Home/fisica.png
nothing change, I see the image, while I think that one of this has a wrong path...
In my application I am using the following code to save images/files into the application’s document directory:
-(void)saveImageDetailsToAppBundle{
NSData *imageData = UIImagePNGRepresentation(userSavedImage); //convert image into .png format.
NSFileManager *fileManager = [NSFileManager defaultManager];//create instance of NSFileManager
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //create an array and store result of our search for the documents directory in it
NSString *documentsDirectory = [paths objectAtIndex:0]; //create NSString object, that holds our exact path to the documents directory
NSString *fullPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.png",txtImageName.text]]; //add our image to the path
NSLog(fullPath);
[fileManager createFileAtPath:fullPath contents:imageData attributes:nil]; //finally save the image
NSLog(#"image saved");
}
However, there is a problem with the image name. If a file exists in the documents directory, the new file with the same name will overwrite the old file. How can I check if the file name exists in the documents directory?
Use NSFileManager's fileExistsAtPath: method to check if it exists or not.
usage
if ( ![fileManager fileExistsAtPath:filePath] ) {
/* File doesn't exist. Save the image at the path */
[fileManager createFileAtPath:fullPath contents:imageData attributes:nil];
} else {
/* File exists at path. Resolve and save */
}
if ([[NSFileManager defaultManager] fileExistsAtPath:myFilePath])
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:#"file name"];
if([fileManager fileExistsAtPath:writablePath]){
// file exist
}
else{
// file doesn't exist
}
As Apple Documentation says it is better to perform some action and then handle no file existance than checking if file is existing.
Note: Attempting to predicate behavior based on the current state of the file system or a particular file on the file system is not recommended. Doing so can cause odd behavior or race conditions. It's far better to attempt an operation (such as loading a file or creating a directory), check for errors, and handle those errors gracefully than it is to try to figure out ahead of time whether the operation will succeed. For more information on file system race conditions, see “Race Conditions and Secure File Operations” in Secure Coding Guide.
In the Simulator I can save an NSMutableArray to a file and read it back with the following code:
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:#"RiskValues"]){ // If file exists open into table
NSLog(#"Risk Values File Exists");
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullFileName = [NSString stringWithFormat:#"RiskValues", documentsDirectory];
gRiskValues = [[NSMutableArray alloc] initWithContentsOfFile:fullFileName];
gRiskValuesAlreadyInitialised = YES;
} else {
NSLog(#"Can't find RiskValues file, so initialising gRiskValues table");
Do something else .......
}
This doesn't work on the device. I have tried to locate the file using the following but it still doesn't work:
NSString *fullFileName = [documentsDirectory stringByAppendingPathComponent#"RiskValues"];
What am I doing wrong?
Great answers from everyone. I have resolved the file path and existence issues at a stroke. Many, many thanks.
You have to provide absolute path here:
if ([fileManager fileExistsAtPath:#"RiskValues"])
So it must look like this:
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullFileName = [documentsDirectory stringByAppendingPathComponent:#"RiskValues"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath: fullFileName]){ // If file exists open into table
NSLog(#"Risk Values File Exists");
gRiskValues = [[NSMutableArray alloc] initWithContentsOfFile:fullFileName];
gRiskValuesAlreadyInitialised = YES;
} else {
NSLog(#"Can't find RiskValues file, so initialising gRiskValues table");
Do something else .......
}
NSString *fullFileName = [NSString stringWithFormat:#"RiskValues", documentsDirectory];
this line, you're not creating your full path string right. what you should do is
NSString *fullFileName = [documentsDirectory stringByAppendingPathComponent:#"RiskValues"];
also this check
if ([fileManager fileExistsAtPath:#"RiskValues"])
Will never pass on iOS as it is not a full path to any place you are allowed to write at in your sandbox. I suppose it works on the simulator because on the mac it's looking up relatively to the HD root (or something, not sure how the mac file system works :) ), but on the iOS you're going to have to give it a path to a file/directory in your documents (maybe by appending #"RiskValues" to it or whatever)
1) [NSString stringWithFormat:#"RiskValues", documentsDirectory] is just #"RiskValues". So this name points to file in application's directory.
2) [fileManager fileExistsAtPath:#"RiskValues"] searches for file in application directory. It's available for read/write in simulator (it's in your computer file system after all) but it's read-only on device.
BTW (NSFileManager Class Reference)
Attempting to predicate behavior based
on the current state of the file
system or a particular file on the
file system is not recommended. Doing
so can cause odd behavior in the case
of file system race conditions. It's
far better to attempt an operation
(such as loading a file or creating a
directory), check for errors, and
handle any error gracefully than it is
to try to figure out ahead of time
whether the operation will succeed.
Solution:
1) Do not check file presence. Just try to make dictionary with initWithContentsOfFile:encoding:error:
2) You want it to be in documents directory so construct path like this
[documentsDirectory stringByAppendingPathComponent:#"RiskValues"];
I am supposed to have downloaded a file on the iPad simulator, using an appication.
How can I check that this file is present on the iPad simulator file system ?
Is there some file manager that I can use to check the existence of the file and possibly its contents?
You can find the simulator at
/Username/Library/Application
Support/iPhone Simulator/4.2/
where "4.2" is the SDK version.
Under that folder you find all applications in cryptical subfolders. One of them is yours.
In there you'lss find "Documents" which is your app's personal folder.
Use these methods, you can verify a file is present in the documents directory. I've not tested this exact example but it should work.
Example:
NSString *filePath = [self dataFilePathInDocuments:#"MyFile.txt"];
if([self fileExistsAtPath:filePath]) {
NSLog(#"The file exits at %#", filePath);
} else {
NSLog(#"The doesn't exist at %#", filePath);
}
Code:
- (NSString *)dataFilePathInDocuments:(NSString*)aFilename {
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDirectory = [paths objectAtIndex:0];
return [docDirectory stringByAppendingPathComponent:aFilename];
}
- (BOOL) fileExistsAtPath:(NSString*)aFilepath {
NSFileManager *fm = [NSFileManager defaultManager];
return [fm fileExistsAtPath:aFilepath];
}