How to read a file without extension in Objective C - ios

I have a file stored in my iOS App Documents directory. It is a plist file but without .plist file extension. I want to read its content from code but i cant open the file without extension. Is there any way to add plist extension or convert the file into plist, or any way to read content of a file without extension.
This is how my code look like
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"sample.bookmarks"];
filePath = [filePath stringByAppendingPathExtension:#"plist"];
NSDictionary *dict=[NSDictionary dictionaryWithContentsOfFile:filePath];
Thanks in Advance
PS : If I add the .plist extension in finder(by some method) I can open the file and see the content. So I am sure about its type.

It should be possible to load the Plist file whether it has a .plist extension or not. Assuming the Plist filename is sample.bookmarks then the following should load the Plist. I am assuming the root element of the Plist is a dictionary because you state that the Plist can be opened if it has a .plist extension.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"sample.bookmarks"];
NSDictionary *dict=[NSDictionary dictionaryWithContentsOfFile:filePath];
The only change is that I've removed the line that adds a plist extension to the filePath.
The filePath = [filePath stringByAppendingPathExtension:#"plist"]; line will change the filename portion of the filePath to sample.bookmarks.plist. If you changed the extension to an empty string (filePath = [filePath stringByAppendingPathExtension:#""];) then the filename will be changed to sample.bookmarks. which is not the same as sample.bookmarks.

Try with this.
pathToFile = [pathToFile stringByAppendingPathExtension:#"plist"];

Related

Can we set data from a plist to Keychain in iOS?

Can we set data from a plist to Keychain in iOS? If we can do what is the correct approach. Also please let me know if there is any regular tutorial on the same.
Why do you want to save the data in keychain? probably because it is safe. Then you can use NSKeyedArchiver to save the encoded the plist data.
to store the encoded data in plist:
[NSKeyedArchiver archiveRootObject:data toFile:dataPath];
For your questions to get the data from plist file:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths firstObject];
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:#"filename.plist"];
ObjectClassName *fetchedObject = [NSKeyedUnarchiver unarchiveObjectWithFile:dataPath];
to store the data in keychain:
[UICKeyChainStore setString:userPassword forKey:keychainKeyUserPassword];

Saved photos don't appear on device after update

On my iPhone app, I'm saving pictures associated with an event via this code:
[pngData writeToFile:filePath atomically:YES]; //Write the file
self.thisTransaction.picPath = filePath;
Later I retrieve and display the photo with this code:
UIImage * image = [UIImage imageWithContentsOfFile:thisTransaction.picPath];
Works great on my iPad (I don't have an iPhone).
However, if I update the app by connecting the iPad to my MB Pro after an Xcode code modification not involving the above lines, then disconnect and run it independently, the picture at the expected picPath is not retrieved. All other data associated with thisTransaction in Core Data is intact and unchanged, but the expected picture doesn't appear on the device after the update.
Can someone please tell me where I'm going wrong?
Edit to clarify file path construction
pngData = UIImagePNGRepresentation(capturedImage.scaledImage);
NSLog(#"1 The size of pngData should be %lu",(unsigned long)pngData.length);
//Save the image someplace, and add the path to this transaction's picPath attribute
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory
int timestamp = [[NSDate date] timeIntervalSince1970];
NSString *timeTag = [NSString stringWithFormat:#"%d",timestamp];
filePath = [documentsPath stringByAppendingPathComponent:timeTag]; //Add the file name
NSLog(#"1 The picture was saved at %#",filePath);
The console log shows this filePath:
/Users/YoursTruly/Library/Developer/CoreSimulator/Devices/65FB33E1-03A7-430D-894D-0C1893E03120/data/Containers/Data/Application/EB9B9523-003E-4613-8C34-4E91B3357F5A/Documents/1433624434
The issue you are having is that the location of an app's sandbox can change over time. Typically this happens when an app is updated. So the worst thing you can do is persist absolute file paths.
What you need to do is persist just the part of the path relative to the base path (the "Documents" folder in this case).
Then when you want to reload the file again, append the persisted relative path to the current value of the "Documents" folder.
So your code needs to be something like this:
Save the file:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory
int timestamp = [[NSDate date] timeIntervalSince1970];
NSString *timeTag = [NSString stringWithFormat:#"%d",timestamp];
filePath = [documentsPath stringByAppendingPathComponent:timeTag]; //Add the file name
[pngData writeToFile:filePath atomically:YES]; //Write the file
self.thisTransaction.picPath = timeTag; // not filePath
Load the file:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory
NSString *filePath = [documentsPath stringByAppendingPathComponent:thisTransaction.picPath];
UIImage *image = [UIImage imageWithContentsOfFile:filePath];

Why can't I retrieve my plist file?

I have a plist file I just created of strings; it looks like this:
This is the code I'm using to create the path to the file:
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); // Create a list of paths
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get a path to your documents directory from the list
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"NailServices.plist"]; // Create a full file path
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path]) { // Check if file exists
// Get a path to the plist created before in bundle directory (by Xcode)
NSString *bundle = [[NSBundle mainBundle] pathForResource: #"NailServices" ofType: #"plist"];
[fileManager copyItemAtPath:bundle toPath: path error:&error]; // Copy this plist to your documents directory
}
This is the code I'm using to examine the data (to make sure this is working)... I'm getting a (null) back from the NSLog statement)
//Load Dictionary with wood name cross refference values for image name
NSString *plistDataPath = [[NSBundle mainBundle] pathForResource:#"NailServices" ofType:#"plist"];
NSDictionary *NailServicesDictionary = [[NSDictionary alloc] initWithContentsOfFile:plistDataPath];
NSLog(#"\nnailServicesDict: %#", NailServicesDictionary);
This is my first attempt at creating/using a "strings" plist file; I have read everything I could find on Google and SO without finding an example of a plain ol' strings file. What else do I have to do to be able to get to this plist data?
Your problem is that you are creating an NSDictionary while your plist is an NSArray. Thus, it will return nil when you try to create it as a dictionary because no dictionary exists.
You need to change:
NSDictionary *NailServicesDictionary = [[NSDictionary alloc] initWithContentsOfFile:plistDataPath];
to
NSArray *NailServicesArray = [[NSArray alloc] initWithContentsOfFile:plistDataPath];
As a commenter posted, plist files can either have an NSArray or an NSDictionary as their root. Your example plist has an NSArray as its root, so you'll want to alloc and init an NSArray, not an NSDictionary. If your plist is stored in the app bundle when you build the app in Xcode and you don't need to modify it at runtime, then it's unnecessary to copy it to the NSDocumentsDirectory. Also, I'd recommend using [paths lastObject]; rather than [paths objectAtIndex:0];, which can throw an exception if the paths array is empty.

Retrieve by specific file name from document directory in iOS

Now i am retrieving file from document directory by specific name in iOS with following code.
NSMutableArray *arrayToSearch = [[NSMutableArray alloc] init];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSError * error;
arrayToSearch = (NSMutableArray *)[[NSFileManager defaultManager] contentsOfDirectoryAtPath:[NSString stringWithFormat:#"%#/Manual.txt",documentsDirectory] error:&error];
I am sure i have the Manual.txt file in document directory.
However it doesn't show anything in tableView.
I also reload tableView.
Is there anything wrong?
The method is contentsOfDirectoryAtPath:. Read the name of the method. Read the description in the docs. The path you pass must reference a directory, not a file.
What you are trying to do doesn't make sense logically. If you know a specific file, then why search for it? Why create an array?
If you want to see if the file exists, use the fileExistsAtPath: method of NSFileManager.
If you just want the filename in the array then do:
NSString *filename = [documentsDirectory stringByAppendingPathComponent:#"Manual.txt"];
[arrayToSearch addObject:filename]; // since the array was pre-allocated
Please don't use stringWithFormat to create the filename. Use the proper NSString path methods like I did above.

iOS zip subdirectory documents folder

I'm using ZipKit for iOS I'm trying to zip a subdirectory of my Documents folder. I've referred to this question but it still doesn't seem to be working. My code is:
ZKFileArchive *archive = [ZKFileArchive archiveWithArchivePath:#"Documents/test.zip"];
NSInteger result = [archive deflateDirectory:#"/Documents/test" relativeToPath:#"/Documents" usingResourceFork:NO];
I have a "test" subdirectory and I want to zip it up into test.zip. The "result" returns 1, but no zip folder appears. Any ideas?
Figured it out. For anyone with the same problem, you just need to set the relative path to the actual documents folder:
NSArray *documentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentFolder = [documentPath objectAtIndex:0];
ZKFileArchive *archive = [ZKFileArchive archiveWithArchivePath:#"Documents/test.zip"];
NSInteger result = [archive deflateDirectory:#"/Documents/test" relativeToPath:documentFolder usingResourceFork:NO];

Resources