NSFileManager: Copy file not success - iphone

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?");
}
}

Related

Renaming and moving file using NSFIleManager

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.

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

Copying file from bundle to documents not working (Cocoa error 512)

I am trying to simply copy my sqlite3 database to the documents directory. I get a Cocoa Error 512 and what I figured about that is, that it's not a valid directory (or something like that.
The database file is in my Resources folder in XCode. (The name of file is correct)
Here is the code I am trying to use:
-(void) checkAndCreateDatabase
{
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
//databasePath + databaseName is declared in the header
databaseName = #"WaypointDatabase.sql";
databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
success = [fileManager fileExistsAtPath:databasePath];
if(success)
{
NSLog(#"Database exists");
return;
}
else
NSLog(#"Database does not exists");
NSString *databasePathFromApp = [[NSBundle mainBundle] pathForResource:#"WaypointDatabase" ofType:#"sql"];
if(databasePathFromApp == nil)
{
NSLog(#"ERROR: IT IS NIL");
}
NSError* error = nil;
NSLog(#"Path in bundle:\n%#\n\n", databasePathFromApp);
NSLog(#"Path to copy to:\n%#\n\n", databasePath);
[fileManager copyItemAtPath:databasePathFromApp
toPath:databasePath error:&error];
[fileManager release];
if (error)
{
NSLog(#"%#\n\n", error);
NSLog(#"%#", [error userInfo]);
}
}
And the output to console that I get is:
2011-10-30 10:36:13.242 xxxx[6726:707] Database does not exists
2011-10-30 10:36:13.249 xxxx[6726:707] Path in bundle:
/var/mobile/Applications/FF654016-4257-47BB-99FE-55DB5453BBC6/xxxx.app/WaypointDatabase.sql
2011-10-30 10:36:13.252 xxxx[6726:707] Path to copy to:
/var/mobile/Applications/FF654016-4257-47BB-99FE-55DB5453BBC6/Documents/WaypointDatabase.sql
2011-10-30 10:36:13.268 xxxx[6726:707] Error Domain=NSCocoaErrorDomain Code=512 "The operation couldn’t be completed. (Cocoa error 512.)" UserInfo=0xe8b7cd0 {NSUserStringVariant=(
Copy
), NSFilePath=/var/mobile/Applications/FF654016-4257-47BB-99FE-55DB5453BBC6/xxxx.app/WaypointDatabase.sql, NSDestinationFilePath=/var/mobile/Applications/FF654016-4257-47BB-99FE-55DB5453BBC6/Documents/WaypointDatabase.sql, NSUnderlyingError=0xe8b7ee0 "The operation couldn’t be completed. Not a directory"}
2011-10-30 10:36:13.272 xxxx[6726:707] {
NSDestinationFilePath = "/var/mobile/Applications/FF654016-4257-47BB-99FE-55DB5453BBC6/Documents/WaypointDatabase.sql";
NSFilePath = "/var/mobile/Applications/FF654016-4257-47BB-99FE-55DB5453BBC6/xxxx.app/WaypointDatabase.sql";
NSUnderlyingError = "Error Domain=NSPOSIXErrorDomain Code=20 \"The operation couldn\U2019t be completed. Not a directory\"";
NSUserStringVariant = (
Copy
);
}
I figure this must be to do with getting the directory paths or something, but have been stuck on this for a few days now.
Take note, this works perfectly & without any errors on the simulator.
Where could I have gone wrong?
[UPDATE]
Could this be because the Documents-folder directory does not exist? How would I go about to create/check it?
[UPDATE 2]
I have done some other tests using
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *err = nil;
NSArray *dirArr = [fileManager contentsOfDirectoryAtPath:documentsDir error:&err];
NSLog(#"~~Contents:\n%#",dirArr);
NSLog(#"~~Error: \n%#",err);
And surprisingly it gave Cocoa Error 256 and also said "Not a directory". It is almost as if the Documents directory does not exist. But it does, according toNSSearchPathForDirectoriesInDomains`
Here is the output I got
2011-10-30 10:59:16.934 xxxx[6774:707] ~~Contents:
(null)
2011-10-30 10:59:16.936 xxxx[6774:707] ~~Error:
Error Domain=NSCocoaErrorDomain Code=256 "The operation couldn’t be completed. (Cocoa error 256.)" UserInfo=0x10052580 {NSUserStringVariant=(
Folder
), NSFilePath=/var/mobile/Applications/FF654016-4257-47BB-99FE-55DB5453BBC6/Documents, NSUnderlyingError=0x10054a50 "The operation couldn’t be completed. Not a directory"}
The problem got solved by setting a non standard Bundle ID in die info.plist
I used the Bundle ID from iTunes Connect for this specific app. Now everything works perfectly.
Try changing
[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseName];
for
[[NSBundle mainBundle] pathForResource:#"WaypointDatabase" ofType:#"sql"];
and check that this does not return nil to ensure that the is not what's going wrong apart from that it looks fine to me on first skim.

Not able to write into text file

I need to write a string into a file. For that, my code is:
-(void)writeToFile:(NSString *)fileName: (NSString *)data {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
// the path to write file
NSString *appFile = [documentsDirectory stringByAppendingPathComponent:fileName];
[data writeToFile:appFile atomically:YES];
}
I am calling this method like this
ownServices *obj = [[ownServices alloc]init];
[obj writeToFile:#"iphone.txt" :#"this is mahesh babu"];
but it didn't write into the text file.
What's the reason? Can anyone please help me.
Thank u in advance.
The most likely problem is that the documents directory does not exist. Create it if it doesn't, then write to it:
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
NSString *parentDir = [paths objectAtIndex:0];
/* Create the parent directory.
* This is expected to fail if the directory already exists. */
(void)[[NSFileManager defaultManager]
createDirectoryAtPath:parentDir
withIntermediateDirectories:YES
attributes:nil error:NULL];
NSString *path = [parentDir stringByAppendingPathComponent:fileName];
/* Now write, and if it fails, you'll know why thanks to the |error| arg. */
NSError *error = nil;
BOOL ok = [data writeToFile:path options:NSDataWritingAtomic error:&error];
if (!ok) {
NSLog(#"%s: Failed to write to %#: %#", __func__, path, error);
}
Even simpler would be to use the latest API, which will create the directory for you if it doesn't already exist:
NSError *error = nil;
NSURL *parentURL = [[NSFileManager defaultManager]
URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask
appropriateForURL:nil create:YES error:&error];
if (!parentURL) {
NSLog(#"%s: *** Failed to get documents directory: %#", __func__, error):
return;
}
NSURL *furl = [parentURL URLByAppendingPathComponent:fileName];
error = nil;
BOOL ok = [data writeToURL:furl options:NSDataWritingAtomic error:&error];
if (!ok) {
NSLog(#"%s: *** Failed to write to %#: %#", __func__, furl, error);
}
Firstly, you are calling your method strangely. Rename the method to
-(void)writeString:(NSString *) data toFile:(NSString *)fileName
and call it like so:
[obj writeString:#"this is mahesh babu" toFile:#"iphone.txt"];
Secondly, writeToFile:atomically: is deprecated, use writeToFile:atomically:encoding:error::
NSError *error = nil;
BOOL success = [data writeToFile:appFile atomically:YES encoding:NSUTF8Encoding error:&error];
if (!success) {
NSLog(#"Error: %#", [error userInfo]);
}
This way, you also see what the error is.
Your code looks OK. Use the debugger (or an NSLog statement) to verify the values of data and appFile. If data is nil, nothing will happen (including no errors) because sending a message to nil is a no-op. It's also possible that appFile is not the path you think it is.
Check the permissions of the directory you are trying to write to (ls -la). On the device you can't, but on the simulator you can. Is it read-only for you? Is it owned by another user?
Assuming that isn't the problem, try calling with atomically:NO. Atomic file writing is performed by writing a file, then renaming it to replace the old one. If the problem is there, that will isolate the problem.
Bonus Style Critique
Class names should start with an uppercase letter: OwnServices instead of ownServices
Although your method name is perfectly valid, it's unusual to have two parameters with no words to separate them. A name like writeToFile:string: would be better.
Don't name a variable data if it is meant to point to an instance of something other than NSData. It's confusing, and there's almost a better (more specific) word you can use beside "data".

How to directly store SQLite data in XCode?

Searched on here and got some vague answers, so I thought i'd rephrase the problem to get some clearer answers-
Right now I have an SQL Lite db that reads/parses information from a pre-formatted .txt file. When I open the app, there is a slight 'lag' as the iDevice parses the info, then gets fetched for the iDevice. I'm just wondering if there's any way to just 'save' all the information directly in the xCode so there's no lag/fetch time?
Thank you.
What you can do is pre-build your sqlite database and then include it as a resource in your application. As this database is inside your application bundle it will be read only on your device so you will need to make a copy of it in your application document area.
I have successfully used something like the following code in a production iPhone application
NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentFolderPath = [searchPaths objectAtIndex: 0];
NSString* dbFilePath = [documentFolderPath stringByAppendingPathComponent: DATABASE_FILE_NAME];
if(![[NSFileManager defaultManager] fileExistsAtPath: dbFilePath]) {
// copy the template database into the right place
NSError* error = nil;
[[NSFileManager defaultManager] copyItemAtPath: [[NSBundle mainBundle] pathForResource: #"template" ofType: #"db"] toPath: dbFilePath error: &error];
if(error) {
#throw [NSException exceptionWithName: #"DB Error" reason: [error localizedDescription] userInfo: nil];
}
}
int dbrc; // database return code
dbrc = sqlite3_open ([dbFilePath UTF8String], &db);
if(IS_SQL_ERROR(dbrc)) {
#throw [NSException exceptionWithName: #"DB Error" reason: NSLocalizedString(#"Could not open database", #"Database open failed") userInfo: nil];
}