iOS: get filenames from documents directory into NSMutableArray - ios

Here is kind of an overview of what I'm trying to do. My app has a form on it, and the form data is saved as a .csv file in the documents directory. I want to parse through the documents directory and get the filenames of the files that are .csv files. I then want to display these filenames in a UITableView so that the user can choose a file to be attached to the email. I'm having some trouble getting the filenames into an NSMutableArray. Below is my code:
NSString *extension = #"csv";
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSError *error = nil;
NSArray *documentArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectory error:&error];
NSLog(#"files array %#", documentArray);
NSString *filename;
for (filename in documentArray) {
if ([[filename pathExtension] isEqualToString:extension])
{
[_mySingleton.filePathsArray addObject:filename];
}
}
NSLog(#"files array %#", _mySingleton.filePathsArray);
The first NSlog returns what looks to be all the filenames in the folder. In the second NSlog it should only be printing the .csv filenames, instead it is returning null. Obviously that code in the for loop is not working, how can I fix this? Also I hope it is not confusing, I have a singleton class and in this case I'm storing the filenames in it so that they can be edited and accessed across multiple views.
Thanks,
Alex

try to use built in a filter function
NSArray *files = #[#"11.csv", #"22.txt", #"333.csv", #"444.doc"];
NSArray *cvsFiles = [files filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSString *evaluatedObject, NSDictionary *bindings) {
return [evaluatedObject hasSuffix:#".csv"];
}]];
NSLog(#"%#", cvsFiles);
And in your code the filePathsArray will have only names of files. You should append a directory path to.
[_mySingleton.filePathsArray addObject:[documentsDirectory stringByAppendingPathComponent:filename];
full version
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSArray *documentArray = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectory error:nil];
NSArray *cvsFiles = [documentArray filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSString *evaluatedObject, NSDictionary *bindings) {
return [evaluatedObject hasSuffix:#".csv"];
}]];
NSMutableArray *filePaths = [#[] mutableCopy];
for (NSString *fileName in cvsFiles) {
[filePaths addObject:[documentsDirectory stringByAppendingPathComponent:fileName]];
}
_mySingleton.filePathsArray = filePaths

You wrote
In the second NSlog it should only be printing the .csv filenames,
instead it is returning null.
It means that _mySingleton.filePathsArray is not initialised. In case it will be initialised NSLog will print an empty array, not null.
What you have to do - add _mySingleton.filePathsArray initialisation somewhere before it is used:
_mySingleton.filePathsArray = [NSMutableArray new];

Related

How to make a .plist file

I have an api inside are the city's ID, I do not want to request data every time,I want to writeToFile as plist,but the first written is too slow and memory skyrocketing.
Is there any method I can use to make it into a plist as local file,so users do not have to write again
Plist file obtained in this way is no data on the xcode view, but in fact it has already been written, you can find data through code
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *plistPath = [paths objectAtIndex:0];
NSMutableArray *marr = [NSMutableArray array];
NSString *filename=[plistPath stringByAppendingPathComponent:#"city.plist"];
NSLog(#"filename == %#",filename);
[marr addObject:#"字符串"];
[marr writeToFile:filename atomically:YES];
If you are about to create Plist without programmatically then follow these steps :
Right Click on Files and Select 'New File...' option.
Choose Resources from OS X tab.
An option for Property List is available.
Select an give an appropriate name.
This gets added to your project.
You can create a property list in Objective-C if all of the objects in the aggregate derive from the NSDictionary, NSArray, NSString, NSDate, NSData, or NSNumber class.
Use following code:
//Get the documents directory path
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"plist.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path]) {
path = [documentsDirectory stringByAppendingPathComponent: [NSString stringWithFormat:#"plist.plist"] ];
}
NSMutableDictionary *data;
if ([fileManager fileExistsAtPath: path]) {
data = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
}
else {
// If the file doesn’t exist, create an empty dictionary
data = [[NSMutableDictionary alloc] init];
}
//To insert the data into the plist
[data setObject:#"iPhone 6 Plus" forKey:#"value"];
[data writeToFile:path atomically:YES];
//To retrieve the data from the plist
NSMutableDictionary *savedValue = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
NSString *value = [savedValue objectForKey:#"value"];
NSLog(#"%#",value);
For more details click here
Apple has also put a demo project for creating plist file here.
I wrote a class that caches API responses, so later when u request Countries endpoint, it will check defined endpoints to cache, if it find it in list and it exist in cache, it will return the cached one and will not complete performing the HTTP request, in docs i provided steps how to implement it.
MGCacheManager
Following function take serilizable object(dictionary, array) as input and convert it into plist and write it in document disrectory of application:
+ (BOOL) writeBundelPlist : (NSString *) plistName with : (id) newPlistData {
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:plistName];
if (![fileManager fileExistsAtPath:plistPath]) {
NSString *bundle = [[NSBundle mainBundle] pathForResource:[plistName stringByDeletingPathExtension] ofType:[plistName pathExtension]];
NSLog(#"plistPath = %#", plistPath);
[fileManager copyItemAtPath:bundle toPath:plistPath error:&error];
}
return [newPlistData writeToFile:plistPath atomically:YES];
}
this method is very useful, thanks for evervone,thanks for rmaddy
do{
let data = try NSPropertyListSerialization.dataWithPropertyList(response.result.value as! NSMutableDictionary, format: NSPropertyListFormat.XMLFormat_v1_0, options: 0)
data.writeToFile(countryListPath, atomically: true)
}catch
{
}

Writing/ Appending data to Plist returns nill

I am writing data to plist with always returns me the nil value.. I have to append data also to the previous values of array. But Values are always null..
Below is the code:
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
// get documents path
NSString *documentsPath = [paths objectAtIndex:0];
// get the path to our Data/plist file
NSString *plistPath = [documentsPath stringByAppendingPathComponent:#"a.plist"];
// set the variables to the values in the text fields
// create dictionary with values in UITextFields
NSDictionary *plistDict = [NSDictionary dictionaryWithObject:#"c" forKey:#"Id"];
if ([[NSFileManager defaultManager] fileExistsAtPath:plistPath])
{
array = [[NSMutableArray alloc] initWithContentsOfFile:plistPath];
[array addObject:plistDict];
[array writeToFile:plistPath atomically:YES];
NSLog(#"array%#",array);
}
else
{
NSArray *array = [NSArray arrayWithObject:plistPath];
[array writeToFile:plistPath atomically:YES];
}
If I understand your question correctly, I tested the code with just one little change i.e, Added array declaration and it's working fine. Please pardon me if this is not the issue.
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
// get documents path
NSString *documentsPath = [paths objectAtIndex:0];
// get the path to our Data/plist file
NSString *plistPath = [documentsPath stringByAppendingPathComponent:#"a.plist"];
// set the variables to the values in the text fields
NSMutableArray *array;
// create dictionary with values in UITextFields
NSDictionary *plistDict = [NSDictionary dictionaryWithObject:#"c" forKey:#"Id"];
if ([[NSFileManager defaultManager] fileExistsAtPath:plistPath])
{
array = [[NSMutableArray alloc] initWithContentsOfFile:plistPath];
[array addObject:plistDict];
[array writeToFile:plistPath atomically:YES];
NSLog(#"array%#",array);
}
else
{
NSArray *array = [NSArray arrayWithObject:plistPath];
[array writeToFile:plistPath atomically:YES];
}

Load file string names into an array from Documents Directory

I want to add a list of Files in Document Directory to an Array of Strings. Not sure exactly how to do this, this is what I have so far. I want to load/store only the files that contain the word 'bottom' in the filename in the array. How do i do this exactly?
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSFileManager *fileMan = [[NSFileManager alloc]init];
NSArray *files = [fileMan contentsOfDirectoryAtPath:documentsDirectory error:nil];
for(int i =0; i<files.count; i++){
}
NSString *path = [documentsDirectory stringByAppendingPathComponent:[NSString rangeOfString:#"bottom"]];
//THIS IS HARDCODED ARRAY OF FILE-STRING NAMES
NSArray *bottomArray =[NSArray arrayWithObjects: #"bottom6D08B918-326D-41E1-8A47-B92F80EF07E5-1240-000005EB14009605.png", #"bottom837C95CF-85B2-456D-8197-326A637F3A5B-6021-0000340042C31C23.png", nil];
You need to check each file in the files array:
NSFileManager *fileMan = [NSFileManager defaultFileManager];
NSArray *files = [fileMan contentsOfDirectoryAtPath:documentsDirectory error:nil];
NSMutableArray *bottomArray = [NSMutableArray array];
for (NSString *file in files) {
if ([file rangeOfString:#"bottom"].location != NSNotFound) {
[bottomArray addObject:file];
}
}
In addition to #rmaddy's approach, another option is to use an instance of NSPredicate to filter the array of file names:
NSArray *filenames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:NULL];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"self contains 'bottom'"];
NSArray *matchedNames = [filenames filteredArrayUsingPredicate:predicate];

How do I remove the file extension from a list of files in an NSArray in iOS 5

Working in iOS 5 I have read a list of file names from my documents directory the array is called "file list". I am trying to get a list of file names without extensions. Only the last name in my list has the extension removed. Any ideas?
- (IBAction)getFile:(id)sender
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory =[paths objectAtIndex:0];
NSArray *fileList = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectory error:nil];
NSString *names = [[[fileList valueForKey:#"description"]componentsJoinedByString:#"\n"]stringByDeletingPathExtension];
NSLog(#"File Name Is \n%#",names);
showFile.text = names;
}
- (IBAction)getFile:(id)sender
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory =[paths objectAtIndex:0];
NSArray *fileList = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectory error:nil];
NSString *names = nil;
for (NSString *name in fileList){
if (!names) names = [[name lastPathComponent] stringByDeletingPathExtension];
else names = [names stringByAppendingFormat:#" %#",[[name lastPathComponent] stringByDeletingPathExtension]];
}
NSLog(#"File Name Is \n%#",names
}
Looks like you are using the description of the array to get the full array contents, and then you are removing the file extension for the whole thing rather than from each individual file. Try removing the filename extensions first:
NSMutableArray *newArray = [NSMutableArray arrayWithCapacity:[fileList count]];
[fileList enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[newArray addObject:[obj stringByDeletingPathExtension]];
}];
NSString *names = [newArray componentsJoinedByString:#"\n"];
showFile.text = names;
The enumerateObjectsUsingBock method goes through each item in the array. In the code block you take that object, delete the path extension, and add it to a new array. After the full array has been processed, you can them use componentsJoinedByString to add the newline between each filename.

getting data from plist to NSMutableArray and writing the NSMutableArray to same plist iPhone

Using this code I am trying to get the data from Templates.plist file but I am getting null value in array.
//from plist
NSString *path = [[NSBundle mainBundle] pathForResource:#"Templates" ofType:#"plist"];
NSMutableArray *arry=[[NSMutableArray alloc]initWithContentsOfFile:path];
NSLog(#"arrayArray:::: %#", arry);
This is my plist file:
Also I want to know how can I add more strings to this plist file and delete a string from this plist.
First off you cannot write to anything in you mainBundle. For you to write to you plist you need to copy it to the documents directory. This is done like so:
- (void)createEditableCopyOfIfNeeded
{
// First, test for existence.
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:#"Template.plist"];
success = [fileManager fileExistsAtPath:writablePath];
if (success)
return;
// The writable file does not exist, so copy from the bundle to the appropriate location.
NSString *defaultPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"Template.plist"];
success = [fileManager copyItemAtPath:defaultPath toPath:writablePath error:&error];
if (!success)
NSAssert1(0, #"Failed to create writable file with message '%#'.", [error localizedDescription]);
}
So calling this function will check if the file exists in the documents directory. If it doesn't it copies the file to the documents directory. If the file exists it just returns. Next you just need to access the file to be able to read and write to it. To access you just need the path to the documents directory and to add your file name as a path component.
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [docDir stringByAppendingPathComponent:#"Template.plist"];
To get the data from the plist:
NSMutableArray *array = [[NSMutableArray alloc] initWithContentsOfFile:filePath];
To write the file back to the documents directory.
[array writeToFile:filePath atomically: YES];
-(NSMutableArray *)start1
{
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:#"Templates.plist"];
if ([[NSFileManager defaultManager] fileExistsAtPath:plistPath]){
plistArr = [NSMutableArray arrayWithContentsOfFile: plistPath];
}
else {
plistArr = [[NSMutableArray alloc] init];
}
return plistArr;
}
- (void)createNewRecordWithName:(NSMutableDictionary *)dict
{
plistArr=[self start1];
[plistArr addObject: dict];
//[dict release];
[self writeProductsToFile:plistArr];
}
- (void)writeProductsToFile:(NSMutableArray *)array1 {
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:#"Template.plist"];
[array1 writeToFile:plistPath atomically:YES];
}
To get a plist into a mutable array, use this class method:
NSMutableArray *array = [NSMutableArray arrayWithContentsOfFile:path];
Then, add/delete strings from the array. To save the array back to a plist, use:
[array writeToFile:path atomically:YES];

Resources