Not able to create files in caches directory - ios

I'm trying to set up a caches directory for use in my app, but the files are not being created for a reason unknown to me. What am I doing wrong? Here are the methods I'm using:
In class Utilities:
+(NSString *)imageCachePath {
NSString *cacheDirectory = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *pieceImagesDirectory = [cacheDirectory stringByAppendingPathComponent:#"PieceImages"];
NSLog(#"imageCachPath is %#",pieceImagesDirectory);
return pieceImagesDirectory;
}
+ (void)cacheImage:(UIImage *)image usingName:(NSString *)name;
{
NSLog(#"Caching image %#",name);
NSString *pieceImagesDirectory = [self imageCachePath];
BOOL isDir = NO;
NSError *error;
if (! [[NSFileManager defaultManager] fileExistsAtPath:pieceImagesDirectory isDirectory:&isDir] && isDir == NO) {
[[NSFileManager defaultManager]createDirectoryAtPath:pieceImagesDirectory withIntermediateDirectories:YES attributes:nil error:&error];
NSLog(#"Error after creating directory:\n%#",error);
} else {
// file exists - I don't expect to use the else block. This is for figuring out what's going on.
NSLog(#"File %# exists -- is it a directory? %#",pieceImagesDirectory, isDir?#"YES":#"NO");
}
NSString *nameToUseInFilename = [name stringByReplacingOccurrencesOfString:#" " withString:#"_"];
NSString *fullPath = [pieceImagesDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.png",nameToUseInFilename]];
NSData *data = UIImagePNGRepresentation(image);
NSFileManager *fileManager = [NSFileManager defaultManager];
//Save the file, overwrite existing if exists.
NSLog(#"Attempting to create file at path %# with %d bytes of data",fullPath, [data length]);
if ([fileManager createFileAtPath:fullPath contents:data attributes:nil]) {
NSLog(#"Success");
} else {
NSLog(#"Error creating file");
}
}
In the class where the images are created, I call the method thus:
// image is an object of type UIImage
// cachedImageName is a string that resolves to something like User Image/12
[Utilities cacheImage:image usingName:cachedImageName];
Here are sample NSLog output lines in the debugger:
... Caching image User Image/12
... imageCachPath is /var/mobile/Applications/5EBB1152-5CC1-4A30-ABD5-B4C9A60E4CB4/Library/Caches/PieceImages
... File /var/mobile/Applications/5EBB1152-5CC1-4A30-ABD5-B4C9A60E4CB4/Library/Caches/PieceImages exists -- is it a directory? YES
... Attempting to create file at path /var/mobile/Applications/5EBB1152-5CC1-4A30-ABD5-B4C9A60E4CB4/Library/Caches/PieceImages/User_Image/12.png with 12071 bytes of data
... Error creating file

The call to NSFileManager fileExistsAtPath:isDirectory: gives you an indeterminate value for isDir if the directory doesn't exist. You should change your code to:
BOOL isDir = NO;
NSError *error;
if (! [[NSFileManager defaultManager] fileExistsAtPath:pieceImagesDirectory isDirectory:&isDir]) {
[[NSFileManager defaultManager]createDirectoryAtPath:pieceImagesDirectory withIntermediateDirectories:YES attributes:nil error:&error];
NSLog(#"Error after creating directory:\n%#",error);
} else {
// file exists - I don't expect to use the else block. This is for figuring out what's going on.
NSLog(#"File %# exists -- is it a directory? %#",pieceImagesDirectory, isDir?#"YES":#"NO");
}
It also appears that you add a second folder User_Image to the path. You never create this directory.
I would also suggest you change how you write the image data. Instead of using NSFileManager createFileAtPath:contents:attributes:, use NSData writeToFile:options:error:. Then you can get an error object providing more details of any problem.
In the end it may be best to build the full path to the file. Strip off the last path component (the actual filename) and then check for the existence of the remaining path. Then make one call to createDirectoryAtPath... and let it create any all all needed folders.

Related

Proper way to giving name to file when [NSData writeToFile:] used

I'm using that code to save downloaded videos from internet to application document folder:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *save_it = [documentsDirectory stringByAppendingPathComponent:video_filename];
NSError *error;
BOOL success = [fileData writeToFile:save_it options:0 error:&error];
if (!success) {
NSLog(#"writeToFile failed with error %#", error);
}
it works, but if there is a slash "/" in the video_filename it breaks because of slash is directory seperator, I know.
For example when video_filename is : Best Video / Best Song Ever.3gpp , log says:
{NSFilePath=/Users/Apple/Library/Developer/CoreSimulator/Devices/5A7D36F5-6EDB-495D-9E8E-B9EB22E5357C/data/Containers/Data/Application/B1D0AC48-D84C-4A0D-9F09-08BF4C45DD32/Documents/Best Video / Best Song Ever.3gpp, NSUnderlyingError=0x7d339430 "The operation couldn’t be completed. No such file or directory"}
I don't know is there any other special character that will make crashing,
So what is the best way of cleaning these special characters from nsstring ?
We can make SEO friendly urls in PHP, I'm searching a function like that to do this.
The first problem I see here is that your file path includes some spaces. in the example you gave, the value of video_filename variable is "Best Video / Best Song Ever.3gpp" which includes spaces around the slash. You first have to delete the spaces, this might help you do that:
NSArray *components = [video_filename componentsSeparatedByString:#"/"];
for (NSInteger i = 0, i < components.count, ++i) {
NSString *string = components[i];
string = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
components[i] = string;
}
NSString *path = [components componentsJoinedByString:#"/"];
If I understood correctly, your video_filename might be either in the form xxx.3gpp or yyy/xxx.3gpp. If it's the format of yyyy/xxxx.3gpp, you first have to create a directory named yyyy and then save the file to that directory.
This might help you do that:
- (void)createDirectory:(NSString *)directoryName
atFilePath:(NSString *)filePath
{
NSString *filePathAndDir = [filePath
stringByAppendingPathComponent:directoryName];
NSError *error;
if (![[NSFileManager defaultManager] createDirectoryAtPath:filePathAndDir
withIntermediateDirectories:NO
attributes:nil
error:&error]) {
NSLog(#"Create directory error: %#", error);
}
}
and the way you would use this is
[self createDirectory:components[0] atFilePath:documentsDirectory];
hope this helps!
So if your filename is actually "Best Video / Best Song Ever.3gpp" I am sorry but nothing easy comes to mind.
Now if Best Video is a folder where you will save your file you can use :
+(NSString*) getPathToFolder:(NSString*) folderName {
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSString *folderPath = [documentsPath stringByAppendingPathComponent:folderName];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:folderPath]) {
NSLog(#"Creating a new folder at\n%#", folderPath) ;
[fileManager createDirectoryAtPath:folderPath withIntermediateDirectories:NO attributes:nil error:nil];
}
return folderPath ;
}
This will check if your folder exist or not, if it does not exists then it will create it.
it will return the path you will want to use to save your file.
Now regarding the naming of the files, using spaces is highly unadvisable, I suggest using :
NSString* pathWITHSpaces ;
NSString* pathWithoutSpaces = [pathWITHSpaces stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
Hope this helps a bit

Using NSFileManager to return if directory does not exit [duplicate]

This question already has answers here:
How to check if a directory exists in Objective-C
(3 answers)
Closed 8 years ago.
I have the following code that returns an NSArray of the names of files in a given directory. This works fine when the directory exists but what I would like to know is how I can first check whether or not the directory at directoryPath actually exists.
NSString *directoryPath = [documentsDirectory stringByAppendingPathComponent:folderName];
NSArray *directoryContents = [[NSFileManager defaultManager]contentsOfDirectoryAtPath:directoryPath error:nil];
The NSFileManager class has a built in method, which is used to check if a file exists at a path or not.
The function goes like this :
[fileManagerObject fileExistsAtPath : #"PUT_YOUR_FILE_PATH_HERE" isDirectory : YES]; //If its a file that you're looking to check then put isDirectory as NO, but if its a folder then enter YES as the parameter
Here's how you would typically use it in your code :
NSFileManager *fileManager = [[NSFileManager alloc] init];
if([fileManager fileExistsAtPath:#"FILE_PATH_HERE" isDirectory:NO] == YES)
{
//Yes. The file exists, continue with your operation.
}
else
{
//No. The file doesn't exist.
}
Use NSFileManager's fileExistsAtPath:isDirectory: method.
fileExistsAtPath:isDirectory:
Return Value
YES if a file at the specified path exists or NO if the file’s does not exist or its existence could not be determined.
Apple Documentation for NSFileManager
Following NSFileManger API can give the desired results:
fileExistsAtPath:isDirectory:
Use this :
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *pathToDocumentsDir = [paths objectAtIndex:0];
BOOL isDir;
NSString *subfolder = [pathToDocumentsDir stringByAppendingPathComponent:fileExistsAtPath:YOUR_DIRECTORY_NAME];
if (![fileManager fileExistsAtPath:subfolder isDirectory:&isDir]) {
//No directory exist
[fileManager createDirectoryAtPath:subfolder withIntermediateDirectories:NO attributes:nil error:nil];
}
else{
//directory exist
}
Sample code:
NSString *directoryPath = [documentsDirectory stringByAppendingPathComponent:folderName];
BOOL isDirectory;
BOOL isExists = [[NSFileManager defaultManager] fileExistsAtPath:directoryPath isDirectory:&isDirectory];
if (isExists) {
/* file exists */
if (isDirectory) {
/* file is a directory */
}
}

How to check to see if same exact file exists

I am currently using this code to copy my SQLite database, however it is currently only checking to see if the file exists... I want to change it to check if the file isn't exactly the same, for example I am worried if a database gets corrupt or doesn't copy all the way, the app will lose functionality and the only way to fix this would be to delete the App and redownload it.
So how can I compare if two files are exactly equal?
- (void) copyDatabaseIfNeeded {
//Using NSFileManager we can perform many file system operations.
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSString *dbPath = [self getDBPath];
BOOL success = [fileManager fileExistsAtPath:dbPath];
//NSLog(#"%d",success);
if(!success) {
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"database01.sqlite"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];
if (!success)
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
}
- (NSString *) getDBPath
{
//Search for standard documents using NSSearchPathForDirectoriesInDomains
//First Param = Searching the documents directory
//Second Param = Searching the Users directory and not the System
//Expand any tildes and identify home directories.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
//NSLog(#"dbpath : %#",documentsDir);
return [documentsDir stringByAppendingPathComponent:#"database01.sqlite"];
}
You can use contentsEqualAtPath:andPath: method of NSFileManager for this purpose.
Use your code something like this:
......
if(!success) {
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"database01.sqlite"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];
if (!success)
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
success = [fileManager contentsEqualAtPath:defaultDBPath andPath:dbPath]; //verify if file size and content matches
if(!success) {
//report error
}
}
.......
And it should do the trick for you.
Edit - Forget this answer - use the one by Ayan.
Start by comparing the file sizes. If the sizes are different you know the files are not the same. This is a simple and quick check.
If the sizes are the same then you need to compare the files, byte by byte. An inefficient way would be to load both files into NSData objects and see if they are equal. This only works if the files will always be small enough to fit in memory.
A better approach is to open both files as streams and read them in chunks. Compare each chunk (say 2k each) until two chunks are different or you get to the end.

NSFileManager in IOS

- (void)viewDidLoad
{
[super viewDidLoad];
NSFileManager * fileManager =[[NSFileManager alloc]init];
NSArray *Apath=[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
NSString *FilePath=[[Apath objectAtIndex:0] absoluteString];
NSString *TEST =[FilePath stringByAppendingPathComponent:#"test10.txt"];
BOOL flage =[[NSFileManager defaultManager] fileExistsAtPath:TEST];
if (flage)
{
NSLog(#"It's exist ");
}
else
{
NSLog(#"It is not here yet ");
NSData * data =[[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:#"www.google.com"]];
[data writeToFile:TEST atomically:YES];
}
}
I'm just trying to create a text file , it always give me "It is not here yet"
Anything wrong with the code ??
You haven't created a file, you have only created a file path: you need to write a file to that path.
//after these lines ... (I've improved your variable names)
NSArray *paths=[fileManager URLsForDirectory:NSDocumentDirectory
inDomains:NSUserDomainMask];
NSString *filePath=[[paths objectAtIndex:0] absoluteString];
filePath =[filePath stringByAppendingPathComponent:#"test10.txt"];
//try this
NSString* fileContent = #"some text to save in a file";
BOOL success = [fileContent writeToFile:filePath
atomically:YES
encoding:NSUTF8StringEncoding
error:nil]
But watch out - file existence tests come with a warning from Apple:
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.

contentsOfDirectoryAtPath returning null (iOS)

I'm having trouble displaying all files in directory. I did make a directory named "saves" in the same folder as all the app files.
I use this code:
NSError *error = nil;
NSArray *imageFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:#"saves" error: &error];
NSLog(#"FILES: %#", imageFiles);
Can anyone help me out, because this code logs "null" - so pretending there isn't anything in the folder, but in the folder I made one directory and two empty files.
NSString *documentDirPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
Check for files in the test directory:
NSArray *filePaths = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[documentDirPath stringByAppendingPathComponent:#"test"] error:nil]];
It looks to me like you're trying to save a file in your main bundle. Are you doing this on the simulator or on an actual device? You can't save files in your main bundle on a device.
NSError *error = nil;
NSArray *imageFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:#"saves" error: &error];
Not sure what ypou expect this to do...
NSLog(#"FILES: %#", imageFiles);
try this
NSLog(#"Image file count %d", [imageFiles count]);
for ( int i - 0; i <= [imageFiles count] - 1; i++)
{
NSLog(#"file name : %#", [imageFiles objectAtIndex:i]);
}
code NOT tested but I think you get the idea...

Resources