Renaming and moving file using NSFIleManager - iphone

This is my code to rename and move file from a temporary directory to My Documents directory.
So the problem is within two sections of mode Create a Directory and Attempt to move. The rest all is working correctly..
When I comment out the Create directory section, the Attempt to Move section logs in the console:
Unable to Move the File..Error Code 4.
Now I researched error code 4 and it means that the directory does not exist. So I added the code to create the directory.
Now when I run the program the directory is created but the Attempt to Move section logs:
Unable to Move File..error code 512
Now researching on it it is due to the file already exists. The destination must not exist.
So I am pretty confused, since both error codes are contracting each other.
{
NSError *error;
NSFileManager* manager = [[NSFileManager alloc] init];
NSString* tempFile =[NSTemporaryDirectory() stringByAppendingPathComponent:#"recordTest.caf"];
if (tempFile)
{
// Get the Documents Directory
NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
NSLog(#"Documents directory: %#",
[manager contentsOfDirectoryAtPath:documentsDirectory error:&error]);
//Get the User File Save Name from the text field
NSString *UserText = [[self FileNameText] text];
// Rename the file, by moving the file
NSString *filePath2 = [documentsDirectory
stringByAppendingPathComponent:[NSString stringWithString:UserText]];
// Create a Directory
if( [manager createDirectoryAtPath:[NSString stringWithFormat:#"%#/%#",documentsDirectory,UserText] withIntermediateDirectories:NO attributes:nil error:&error]!= YES)
{
NSLog(#"Directory error");
}
if([manager fileExistsAtPath:[NSString stringWithFormat:#"%#/%#",documentsDirectory,UserText]])
{
NSLog(#"Path exist");
NSLog(#"Documents directory: %#",
[manager contentsOfDirectoryAtPath:documentsDirectory error:&error]);
}
// Attempt the move
if ([manager moveItemAtPath:tempFile toPath:filePath2 error:&error] != YES)
{
NSLog(#"Unable to move file: %#", [error localizedDescription]);
}
else
{
if ([manager removeItemAtPath:tempFile error:&error] != YES)
NSLog(#"Unable to delete file: %#", [error localizedDescription]);
}
}
[manager release];
}

The problem is most likely that the file you are trying to move doesn't exist.
replace
if (tempFile) //this will return YES every time, telling you you have a string!
with
if ([manager fileExistsAtPath:tempFile]) //this will tell you if the file exists at that path
A few notes
1. To see with your eyes if the file you are looking for really exists, check the simulator application folders at something similar to this:
/Users/yogevshelly/Library/Application\ Support/iPhone\
Simulator/5.0/Applications
then browse to a specific application
2. Don't just append strings to get folders , do something like this:
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [dirPaths objectAtIndex:0];
3. The following line will create a folder with the file's name as the folders name!:
[manager createDirectoryAtPath:filePath2 withIntermediateDirectories:NO attributes:nil error:&error]
creating a folder from a filename seems weird, what you want to do is either copy the file to an existing directory or first create a directory and copy the file into-it

you use the metod
contentsOfDirectoryAtPath: withIntermediateDirectories: attributes:error
this method create directory but you pass it the filename.
i think you create /Documents/filename/ instead of /Documents/filename

As per my understanding the problem part of the code is following one
// Create a Directory
if( [manager createDirectoryAtPath:[NSString stringWithFormat:#"%#/%#",documentsDirectory,UserText] withIntermediateDirectories:NO attributes:nil error:&error]!= YES)
{
NSLog(#"Directory error");
}
You are creating a folder in with the file name in same location .... try commenting the the above code .. it should work.

Related

Rename the folder of document directory

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))
}

NSFileManager: Copy file not success

I want to copy files located at /Library to the folder /User/Library/AddressBook/Sample/,
I used:
[[NSFileManager defaultManager] copyItemAtPath: #"/Library/MyFile.mp3"
toPath: #"/User/Library/AddressBook/Sample/MyFile.mp3"
error: &error];
But I encountered an error that says `Operation could not be completed. No such file or
directory`
I am working on a jailbroken iPhone.
The directory:
/User/Library/AddressBook/Sample/
does not exist on a phone normally. Have you added the Sample subdirectory, before trying to copy the mp3 file into it?
With the NSFileManager methods, I would also recommend using the error object to help you debug:
NSError* error;
[[NSFileManager defaultManager] copyItemAtPath:#"/Library//MyFile.mp3" toPath: #"/User/Library/AddressBook/Sample/MyFile.mp3" error:&error];
if (error != nil) {
NSLog(#"Error message is %#", [error localizedDescription]);
}
Also, it looks like there is a mistake in your spelling of copyItemAtPath, but probably it's only in your question, and not in your code? Anyway, please double-check.
And, you have a double-slash (//) in your path, too, but I don't think that's hurting you. Just take it out, and be careful when typing :)
Update
If you are just running this app normally, but on a jailbroken phone, your app won't have access to those directories. Apps installed normally, on a jailbroken phone, still are sandboxed. The jailbreak doesn't remove all the rules on the phone. If you install the app in /Applications, like true jailbreak apps are, then that code should work for you.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libraryDirectory = [paths objectAtIndex:0];
NSLog(#"%#",libraryDirectory); // Library path
NSString *AddressBookPath = [libraryDirectory stringByAppendingPathComponent:#"AddressBook"];
if (![[NSFileManager defaultManager] fileExistsAtPath:AddressBookPath])
{
NSError* error;
// Create "AddressBook Dir"
if([[NSFileManager defaultManager] createDirectoryAtPath:AddressBookPath withIntermediateDirectories:NO attributes:nil error:&error])
{
// Create "Sample Dir"
NSString *samplePath = [AddressBookPath stringByAppendingPathComponent:#"Sample"];
if (![[NSFileManager defaultManager] fileExistsAtPath:AddressBookPath])
{
NSError* error;
if([[NSFileManager defaultManager] createDirectoryAtPath:AddressBookPath withIntermediateDirectories:NO attributes:nil error:&error])
{
// Copy Files Now
NSError* error;
NSString *fromPath = [libraryDirectory stringByAppendingPathComponent:#"MyFile.mp3"];
NSString *toPath = [samplePath stringByAppendingPathComponent:#"MyFile.mp3"];
[[NSFileManager defaultManager] copyItemAtPath:fromPath toPath:toPath error:&error];
if (error != nil)
{
NSLog(#"Error message is %#", [error localizedDescription]);
}
}
}
}
else
{
NSLog(#"[%#] ERROR: attempting to write create MyFolder directory", [self class]);
NSAssert( FALSE, #"Failed to create directory maybe out of disk space?");
}
}

copying from main bundle creates a file size zero kb

As part of my app start-up i copy bundle files to my documents directory.
This works fine for three out of four of my files but the fourth one create a Zero KB file.
running on iOS 5.0 sim. I have cleaned the build several times and checked the file name capitalization vis correct.
the file appears in the directory but is zero kb and should be 24K
any help appreciated.
-(BOOL) CheckDBs: (NSString *)dbname
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSString *dbPath = [documentsDir stringByAppendingPathComponent:dbname];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL success = [fileManager fileExistsAtPath: dbPath];
NSLog(#"AppDelegate CheckDatabase: %# = %i", dbPath, success);
if (success) {
//NSLog(#"return YES");
return YES;
}
else {
return NO;
}
} // Complete - checks if files exist in the User Documents directory
-(void) copyDBs: (NSString *) dbname
{
//Using NSFileManager we can perform many file system operations.
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
NSString *dbPath = [documentsDir stringByAppendingPathComponent:dbname];
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:dbname];
BOOL success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];
if (success) {
// Version 4.0 code
//NSDictionary *attribs = [NSDictionary dictionaryWithObject:NSFileProtectionComplete forKey:NSFileProtectionKey];
//success = [fileManager setAttributes:attribs ofItemAtPath:dbPath error:&error];
NSLog(#"AppDelegate copyDatase: %# = %d", dbPath, success);
}
//NSLog(#"AppDelegate copyDatase: %# = %d", dbPath, success);
if (!success) {
NSLog(#"Failed to copy database: '%#'", [error localizedDescription]);
// NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
}
Have you also checked the original file size?
Try resetting your simulator. From the NSFileManager documentation:
If a file with the same name already exists at dstPath, this method
aborts the copy attempt and returns an appropriate error.
Make sure the destination is empty and try again. Also, check the error object.
If all that checks out there has got to be an error in spelling the file name. Check if the exact file exists in bundle, NSLog wherever you use a file name or path, etc. You should find the error. Also check the appropriate folder in the Finder.
Instead of using
[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:dbname]
try
[[NSBundle mainBundle] pathForResource:shortName ofType:#"db"]
Ok I figured out what is causing the problem.
as i run the app the appdidfinishlaunching method is not complete before one of the view controllers is loading. That view controller attempts to access one of the files being copied over from the bundle.
I'm guessing that sqlite creates the file when you attempt to access the database, it creates it with with a zero bytes length.
So when my appdidfinish launching method checks for the existance of the file it exists due to the sql call.
This is usually only going to be a problem prior to the first run of the app as after that the database will exist.
problem now is how do i get the appdidfinish launching to complete prior to the rest being allow to start as the view controller in question is part of the mainwindow.xib

UIFileSharingEnabled juste save files

In my iOS app I would like that user can download some jpg file via iTunes. So I've enabled UIFileSharingEnabled. But users are now able to put files in my app. I would like to block that. Is there a way to do that ?
Thanks !
Don't think you can block it, but you can just delete unwanted files when your app becomes active.
Put some code a bit like the sample below - filling in the test to avoid deleting the files you want to be available in iTunes.
Call this from within applicationDidBecomeActive: in your application delegate.
If you're more cautious you might want to check the user hasn't dropped a jpg file with the same name as the one you've parked there. You could test for sameness of date or some such or, if you've not got many files, just delete everything and write them again when the app becomes active.
- (void) removeUnwantedFiles;
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSArray* directoryContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:inboxPath error:NULL];
if (!directoryContents || [directoryContents count] == 0)
{
return;
}
for (NSString* fileName in directoryContents)
{
if ( /* some test of filename to see if it's one of my kosher files */ ) continue;
NSString* filePath = [documentsDirectory stringByAppendingPathComponent:fileName];
NSError* error = nil;
BOOL success = [[NSFileManager defaultManager] removeItemAtPath:filePath error:&error];
// NSLog(#"Deleting (%#): %#", success ? #"succeeded" : #"failed", [filePath lastPathComponent]);
if (!success)
{
NSLog(#"Error: %#", [error localizedDescription]);
}
}
}

NSFileManager: hide a folder?

I use the below to create folder in document directory , my question is , how to make this folder hidden , such that when I allow itune share this folder not appear to the user
/* Create new directory */
NSFileManager *filemgr;
NSArray *dirPaths;
NSString *docsDir;
NSString *newDir;
filemgr =[NSFileManager defaultManager];
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
newDir = [docsDir stringByAppendingPathComponent:#"Patients"];
NSLog(newDir);
if(! [self SearchForDirectory:newDir] )
{
NSLog(#"directory Not Exists");
if ([filemgr createDirectoryAtPath:newDir withIntermediateDirectories:YES attributes:nil error: NULL] == NO)
{
NSLog(#"Failed to create directory");
}
}
else{
NSLog(#"directory Exists");
}
[filemgr release];
You can make a folder hidden from iTunes file sharing by prepending the folder name with a dot (.). So the path would be Documents/MyHiddenFolder would be called Documents/.MyHiddenFolder
However, it is now recommended that private data files should be stored in the Library directory, or within a sub-directory of it. Please see the following Apple Q&A for more information.
The Documents directory is for the user's documents. If you're trying to hide files from there, chances are they aren't documents and you should be storing the files in one of the other directories. What files are we talking about?
Note that including non-documents in that directory with iTunes file sharing enables is grounds for rejection from the App Store.