contentsOfDirectoryAtPath returning null (iOS) - 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...

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

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.

Not able to create files in caches directory

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.

Getting a -1 from open on iOS, why?

The code is copied below. I am using the documents directory because I know you can write outside of your apps sandbox.
I also compare the string I was using to determine the path to one created by the NSFileManager and they are the same. What do you all think?
- (NSString *)documentsDirectory
{
NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
return [paths objectAtIndex:0];
}
- (void) whateverFunction{
NSString *memfileName = #"memmapfile.map";
NSString *filePath = [[self documentsDirectory] stringByAppendingPathComponent:memfileName];
NSLog(#"Here is the filePath: %#", filePath);
NSLog(#"Other version: %s", [[NSFileManager defaultManager] fileSystemRepresentationWithPath:filePath]);
int memFD = open([filePath cStringUsingEncoding:NSASCIIStringEncoding], O_RDWR);
NSLog(#"I am getting -1 for memFD: %d", memFD);
}
I'd guess your file doesn't exist yet, so of course you can't open it. You should add O_CREAT to your open flags so that it gets created if it doesn't exist:
int memFD = open([filePath cStringUsingEncoding:NSASCIIStringEncoding], O_RDWR|O_CREAT);

NSFileManager creating folders herarichy & not saving plist [open]

The problem is appearing on device not on simulator.
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"Plist1.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSLog(#"documentsDirectory --- %#", documentsDirectory);
NSLog(#"path --- %#", path);
#try
{
if (![fileManager fileExistsAtPath:path])
{
[fileManager copyItemAtPath:documentsDirectory toPath:path error:&error];
}
}
#catch (NSException *exception)
{
NSLog(#" [exception description] -- %#", [exception description]);
}
#finally {
}
[dictEmot writeToFile:path atomically:YES];
// To verify
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
NSLog(#"[dict allKeys] My plist ----- %#", [dict allKeys]);
Above is the code which I have written to save two plist files in my documents directory. same method I use to save my second plist.
[self savePlist:plist1];
[self savePlist:plist2];
My problem is whenever I try to save second plist it creates hierarchy of folders inside documents directory and also not saves my plist2 file with it contents.
once it complets the 2nd method call, my app documents directory looks like below,
Documents
-> plist1
-> plist1
.
.
.
-> plist1
-> plist1
other files
I treid doing on main thread also but same result.
its not even printing exception.
What is my mistake ?
- Why its creating hierarchy ?
I don't know much about iOS but I think your problem is with stringByAppendingPathComponent:#"Plist1.plist" Check your documentation as I am supscious by the word Appending and even if you send new file name as you are hardcoding the value of the filename to Plist1.plist...
Still I am not sure as I have not done iOS coding for a long time now.

Resources