I need to list all files in Documents folder and get their names...because I don't know the name of the files..then I can't use:
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString* foofile = [documentsPath stringByAppendingPathComponent:#"filename" ];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:foofile];
How can I do?
Resuming: I need the name of the .png's files in Documents folder
NSFileManager Class Reference
contentsOfDirectoryAtPath:error: Performs a shallow search of the
specified directory and returns the paths of any contained items.
(NSArray *)contentsOfDirectoryAtPath:(NSString )path error:(NSError *)error Parameters path The path to the directory whose contents you want to enumerate. error On input, a pointer to an error object. If an
error occurs, this pointer is set to an actual error object containing
the error information. You may specify nil for this parameter if you
do not want the error information. Return Value An array of NSString
objects, each of which identifies a file, directory, or symbolic link
contained in path. Returns an empty array if the directory exists but
has no contents. If an error occurs, this method returns nil and
assigns an appropriate error object to the error parameter
Discussion This method performs a shallow search of the directory and
therefore does not traverse symbolic links or return the contents of
any subdirectories. This method also does not return URLs for the
current directory (“.”), parent directory (“..”), or resource forks
(files that begin with “._”) but it does return other hidden files
(files that begin with a period character). If you need to perform a
deep enumeration, use the
enumeratorAtURL:includingPropertiesForKeys:options:errorHandler:
method instead.
The order of the files in the returned array is undefined.
Availability Available in iOS 2.0 and later.
That should fulfill your needs
Related
Does the following method ever return multiple values when used on iOS, and if so, do you have an example of when this happens and how to know which element is the one you asked for?
NSArray* NSSearchPathForDirectoriesInDomains (NSSearchPathDirectory directory, NSSearchPathDomainMask domainMask, BOOL expandTilde );
I am wondering because I am calling it with the parameters for getting a path to the Documents directory (see below), and assuming it returns an array with only one element. It is working just fine, but it occurred to me that I might need to make sure I will never get more than one element back. And if I do get more than one, I wondered how I would know which one is the one I asked for?
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = paths[0];
It's my understanding that on iOS you'll only ever get a single element in the returned array.
I believe it returns an array rather than a single value as it's used by OS X too and tries to be as general purpose as possible. On OS X it can potentially return multiple elements, representing the user's documents directory, the computer's documents directory, and so on, according to the domain mask.
As an aside, note that Apple recommends using the NSFileManager methods URLsForDirectory:inDomains: and URLForDirectory:inDomain:appropriateForURL:create:error: instead, stating that URLs are preferred over path strings.
I have the following, where path is the documents folder. myArray is an NSMutableDictionary. I'm running this in the simulator.
BOOL success = [self.myArray writeToFile:path atomically:YES];
The above always returns no. I can see in the target folder that nothing was written.
The path looks like this:
/Users/username/Library/Application Support/iPhone Simulator/7.1/Applications/79D8982F-9995-4831-83B9-E2749F2261CD/Documents/
Any ideas what I'm doing wrong?
I expect one or more objects within the dictionary cannot be written:
Discussion
This method recursively validates that all the contained
objects are property list objects (instances of NSData, NSDate,
NSNumber, NSString, NSArray, or NSDictionary) before writing out the
file, and returns NO if all the objects are not property list objects,
since the resultant file would not be a valid property list.
Where Property List Objects are (see here):
NSArray, NSDictionary, NSString, NSData, NSDate and NSNumber.
The path points to the Documents directory but not to any particular file in that directory. You can't write a file to a directory, you have to give it a file name. The other obvious possibility would be that self.myArray == nil. Plus what Droppy said is absolutely correct.
/Users/username/Library/Application Support/iPhone Simulator/7.1/Applications/79D8982F-9995-4831-83B9-E2749F2261CD/Documents/
The path just represents a navigation to Documents Directory but not pointing to some kind of file.
Add some file name with the below line and add dictionary to the path
NSArray *sandboxArray=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path= [[arr objectAtIndex:0]stringByAppendingPathComponent:#"login.plist"];
write something similar to the path
In an iPad application, I have a folder with the following files:
1-1-xxxx.dat
1-2-xxxx.dat
...
1-999-xxxx.dat
2-1-xxxx.dat
...
...
999-999-xxxx.dat
Where the xxxx parts are characters determined at run-time when the files are created. The contents of each file depends on the contents of the previous one, and so with each file I create, I need to query the previous file. The problem is, I only know the prefix of the previous file and not the xxxx part, as the 'xxxx' part is essentially random. (The xxxx part is itself determined by the xxxx part of the previous file, with the 1-1-xxxx file being randomly named).
To get access to the file, an initial approach would be:
// For file 1-50-xxxx.dat
NSError *error = nil;
NSFileManager *fm = [NSFileManager defaultManager];
NSArray *allFiles = [fm contentsOfDirectoryAtPath:path error:&error];
for (NSString *file in allFiles) {
if ([file hasPrefix:#"1-49-"]) {
// Determine contents and name of file "1-50-xxxx.dat"
// Create file, break, etc.
}
}
// ... And repeat for many files
This obviously becomes very expensive very quickly. Is there an O(1) way of getting the path of the required file as there will only ever be a single file with a given numeric prefix?
Why don't you build a dictionnary of the names and then lookup in that dictionnary the path? The dictionnary keys would be the prefix and the values the full path.
i.e.: (pseudo-code)
// Build the path dictionnary, that is done only once
currentPrefix = ...
previousXXX = null
foreach file
currentXXX = computeXXX( previousXXX )
dictionnary.put( currentPrefix, computePath( currentPrefix, currentXXX )
// Remember for next iteration
previousXXX = currentXXX
currentPrefix++
endforeach
Then, knowing a prefix, getting the path is easy and fast (how fast depends on the dictionnary implementation used of course): dictionnary.get( prefix )
To build the content of your files, just apply the same logic: on each iteration, remember the previous file's content / suffix and use that instead of computing it again from the start.
Nothing is written in my plist file after this code. What is wrong with my code?
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *finalPath = [path stringByAppendingPathComponent:#"aFile.plist"];
NSMutableDictionary *reqData = [NSMutableDictionary dictionaryWithContentsOfFile:finalPath];
/*
some modifications to "reqData"
*/
[reqData writeToFile:finalPath atomically:YES];
Nothing is written in file. what could be the problem?
You'd better write to Document folder:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES);
NSString *path = [paths objectAtIndex:0];
Update
According to NSDictionary Class Reference:
This method recursively validates that all the contained objects are property list objects (instances of NSData, NSDate, NSNumber, NSString, NSArray, or NSDictionary) before writing out the file, and returns NO if all the objects are not property list objects, since the resultant file would not be a valid property list.
Is there any objects with a type other than these valid ones in your whole dictionary?
You are trying to write the file back to the app bundle.
That's what's most likely causing the error.
What if you try writing it somewhere else (e.g. in your desktop folder)?
If you're including the plist with your application, you'll want to copy that file into the Documents directly when the app first starts up (if it hasn't already been copied there). Then, any read and write operations you want to do on the plist should be done from the copy in the Documents directory instead of the version in the app bundle.
First Thing to remember:
You can read a plist file from resources but you can't modify it.
if you want to modify,
copy that file to Documents directory
copy contents of plist into array or dictionary depending on its type
make changes you want
Finally.... save it back to documents directory
that do the trick
i was wondering why we search a path with NSDocumentDirectory at first here :
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:#"Sports.sqlite"];
and later on we compare this path with another path, using this time resourcePath from the NSBundle :
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath]
stringByAppendingPathComponent:#"Sports.sqlite"];
success = [fileManager copyItemAtPath:defaultDBPath
toPath:writableDBPath error:&error];
What is the difference between both?
In this situation you are (normally one time only, unless you need to restore database) copying the database from your read only bundle into your documents directory so that a user can read/write to it. This is useful if you want to pre-seed a database or just have the structure set up.
Your documents directory is read/write and your bundle is not therefore you need to have the sqlite in your documents directory for it to be used properly.
The first part of code is simply getting you the path for where you want the sqlite file to live in your documents directory. Which ends up being held in writableDBPath.
Next you get the path from your bundle (defaultDBPath) and use the two paths to
... copyItemAtPath:defaultDBPath toPath:writableDBPath ...
This gives you a read/write database that you provide in your bundle. Why would you do this instead of running your SQL on the device to create the schema? This allows you to pre-seed the database with some data. It can sometimes be easier to use a graphical tool to set up and edit your sqlite file
What you mean by "comparing" the two paths?
What I see is a file copy from your app resources directory to the user document directory.
So what is happening is that a default version of Sports.sqlite that is to be bundled with the app (and thus is available in the resources directory) is copied to the user directory where the user can modify it.
The first chunk of code simply build the destination path (a string); the second chunk build the source path (a string) and then makes the copy.
Does it make sense?