Get NSData from a file - ios

I am trying get NSData of an own file.
My code is as follow, but NSData returned is always nil… (As you can see, I check if the file exists previously)
if ([[NSFileManager defaultManager] fileExistsAtPath:path]){
NSData * data = [[NSFileManager defaultManager] contentsAtPath:path];
}
Any idea? Thanks!

It's possible that path is a folder, in which case fileExistsAtPath will return YES, but no data can be read.
You can add some extra debugging by reading the data as follows:
NSError* error = nil;
NSData* data = [NSData dataWithContentsOfFile:path options:0 error:&error];
NSLog(#"Data read from %# with error: %#", path, error);
The log output will display the actual error that occurred.

Use This code it works
NSString *path = [pathURL filePath];
if([[NSFileManager defaultManager] fileExistsAtPath:path)
{
NSData *data = [[NSFileManager defaultManager] contentsAtPath:path];
}
else
{
NSLog(#"File not exits");
}

Related

How to copy NSData contents to temporary file?

I'm downloading what can be a large file from an S3 bucket and want to save it between view controllers to be consumed a short time later. I like the tmp directory because of less limitations on file size and there also does not seem to be a reason for me to save this in the Documents directory.
I can construct a path to tmp with:
NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES];
NSURL *fileURL = [[tmpDirURL URLByAppendingPathComponent:#"image"] URLByAppendingPathExtension:#"png"];
NSLog(#"fileURL: %#", [fileURL path]);
but am unsure how to write/overwrite the downloaded NSData * to that path.
I basically just want to what I can more clearly express with the command line:
wget https://example.com/image.png
cp image.png /tmp/
Looks like the class reference may expose a method to do just this:
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/
EDIT
My solution that works. Ended up being that I needed to use writeToURL. Inspiration taken from here:
http://nshipster.com/nstemporarydirectory/
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/#//apple_ref/occ/clm/NSURL/fileURLWithPath:isDirectory:
#define S3_LATEST_IMAGE_FILEPATH #"test-image.png"
// Write the downloaded result to the filesystem
NSError *error;
NSString *fileName = [NSString stringWithFormat:#"%#_%#", [[NSProcessInfo processInfo] globallyUniqueString], S3_LATEST_IMAGE_FILEPATH];
NSURL *directoryURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]] isDirectory:YES];
[[NSFileManager defaultManager] createDirectoryAtURL:directoryURL withIntermediateDirectories:YES attributes:nil error:&error];
if (error) {
NSLog(#"Error1: %#", error);
return;
}
NSURL *fileURL = [directoryURL URLByAppendingPathComponent:fileName];
NSString *path = fileURL.absoluteString;
NSLog(#"fileURL.absoluteString: %#", path);
[data writeToURL:fileURL options:NSDataWritingAtomic error:&error];
if (error) {
NSLog(#"Error: %#", error);
}
You can directly write the NSData into the path by
NSURL *tmpDirURL = [NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES];
NSURL *fileURL = [[tmpDirURL URLByAppendingPathComponent:#"newest-fw"] URLByAppendingPathExtension:#"zip"];
NSString *path= fileURL.absoluteString;
//data would be the NSData that you get from the S3 bucket
NSError *error;
[[NSFileManager defaultManager] createDirectoryAtURL: fileURL withIntermediateDirectories:NO attributes:nil error:&error];
[data writeToFile:path options:NSDataWritingAtomic error:&error];
NSData's writeToFile method will automatically overwrite the file if it is previously present.

dataWithContentsOfFile return null

NSString *path = dict[#"fileURL"];
NSData *imageData = [NSData dataWithContentsOfFile:path];
imageData is null
dict[#"fileURL"] =
/var/mobile/Containers/Data/Application/0906AB53-CE1F-45EF-8E00-9D0B7C98956C/Documents/ccc/image/1446625127.png
I download the device container and the image did exist.
What's wrong?
It's failed to retrieve your file. Use -dataWithContentsOfFile:options:error: to find why it is failed.
NSError* error = nil;
NSString *path = dict[#"fileURL"];
NSData *data = [NSData dataWithContentsOfFile:path options: 0 error: &error];
if (data == nil)
{
NSLog(#"Failed to read file, error %#", error);
}
else
{
// parse the value
}
I thing you should need to use [NSFileManager defaultManager] to store and fetch the image in your application storage instead of writing static path.
Static path is ok withing the simulator but in the real environment you should need to have the actual path. So [NSFileManager defaultManager] will help you.
if([[NSFileManager defaultManager] fileExistsAtPath:filepath)
{
NSData *data = [[NSFileManager defaultManager] contentsAtPath:filepath];
}
else
{
NSLog(#"File not exits");
}
In filepath you need to pass only your folder and file name. not full path like yours.
IE.
filepath = "Documents/ccc/image/1446625127.png";
NOTE:
This is not a actual answer. This will help you to manage the image into your application storage.

Reading NSData in parts

I am implementing extensions in ios8. In this import function returns a url. I need to read data from it and save in my app.
Here is the code.
NSFileCoordinator *fileCoordinator = [[NSFileCoordinator alloc] init];
NSError *error;
__block NSData *data;
[fileCoordinator coordinateReadingItemAtURL:url options:0 error:&error byAccessor:^(NSURL *newURL) {
data = [NSData dataWithContentsOfURL:newURL];
//saving in document directory
}];
My question is, if file is too big, dataWithContentsOfURL results in crash due to out of memory.
I wanted a method to read data from that url in parts, save in my documents, then read next part and keep appending. Thus it won't have memory issue.
Can someone help.
Found two solutions.
1- Used NSURLConnection. Using NSFileHandle wrote data in file.
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data1{
// [data appendData:data1];
[self.currentFileHandle seekToEndOfFile];
[self.currentFileHandle writeData:data1];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
[self.currentFileHandle closeFile];
self.currentFileHandle = nil;
}
Instead of converting it in data and then saving. Used following to copy file.
NSFileCoordinator* fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
[fileCoordinator coordinateReadingItemAtURL:url options:NSFileCoordinatorReadingWithoutChanges error:nil byAccessor:^(NSURL *newURL) {
NSFileManager * fileManager = [[NSFileManager alloc] init];
NSError * error;
NSArray *paths = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
NSURL *urlDestination = [paths lastObject];
urlDestination = [urlDestination URLByAppendingPathComponent:[url lastPathComponent]];
if([[NSFileManager defaultManager] fileExistsAtPath:[urlDestination relativePath]]){
[[NSFileManager defaultManager] removeItemAtPath:[urlDestination relativePath] error:nil];
}
BOOL success = [fileManager copyItemAtURL:url toURL:urlDestination error:&error];
if (success) {
}
}];
I used 2nd solution. Sorry for wrong alignment. I tried a lot, but not
coming properly.

Troubling creating subdirectory of NSCachesDirectory and adding image to it

EDIT: Solution at the end of the post
I'm having trouble creating a subdirectory of NSCachesDirectory and adding an NSData object to it. I've referred to multiple SO posts related to this but when I debug my code, it tells me that the NSData file in the folder doesn't exist. My code:
NSURL *photoURL = [FlickrFetcher urlForPhoto:self.singlePhotoDictionary
format:FlickrPhotoFormatLarge];
NSData *URLToData = [NSData dataWithContentsOfURL:photoURL];
NSString *cacheDirectory = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *newDirectory = [cacheDirectory stringByAppendingPathComponent:#"Photos"];
BOOL isDir = NO;
NSError *error;
if (! [[NSFileManager defaultManager] fileExistsAtPath:newDirectory isDirectory:&isDir] && isDir == NO)
{
[[NSFileManager defaultManager]createDirectoryAtPath:newDirectory withIntermediateDirectories:NO attributes:nil error:&error];
}
NSString *filePath = [newDirectory stringByAppendingPathComponent:#"thePhotos.jpg"];
NSLog(#"%#", filePath);
//[URLToData writeToFile:filePath atomically:NO];
[[NSFileManager defaultManager] createFileAtPath:filePath contents:URLToData attributes:nil];
NSData *theData = [[NSFileManager defaultManager] contentsAtPath:filePath];
NSArray *contentsInManager = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:newDirectory error:nil];
theData and contentsInManager turn out to be:
theData NSData * 0x00000000
contentsInManager NSArray * 0x00000000
Any help here? The subdirectory exists but the file won't be created inside of it.
As a side question: When do we need to make our own instance of NSFileManager as opposed to using the defaultManager?
Thanks in advance!
SOLUTION: After trial and error, I tried deleting the subdirectory and recreating it. Once I did, the file was able to write to the subdirectory.

NSData writeToFile not working

I cant seem to get nsdata to write to a file. Any ideas what i may be doing wrong. Thanks in advance.
NSString* filename = #"myfile.txt";
NSString *applicationDocumentsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *storePath = [applicationDocumentsDir stringByAppendingPathComponent:filename];
if ([fileManager fileExistsAtPath:applicationDocumentsDir])
NSLog(#"applicationDocumentsDir exists"); // verifies directory exist
NSData *data = [NSData dataWithContentsOfURL:URL];
if (data) {
NSString *content = [[NSString alloc] initWithBytes:[data bytes]
length:[data length] encoding: NSUTF8StringEncoding];
NSLog(#"%#", content); // verifies data was downloaded correctly
NSError* error;
[data writeToFile:storePath options:NSDataWritingAtomic error:&error];
if(error != nil)
NSLog(#"write error %#", error);
}
I keep getting the error
"The operation couldn’t be completed. No such file or directory"
Try
NSString *storePath = [applicationDocumentsDir stringByAppendingPathComponent:#"myfile.txt"];
And
if ([[NSFileManager defaultManager] fileExistsAtPath:storePath])
NSLog(#"applicationDocumentsDir exists");
To get more information, you can use
writeToFile:options:error:
instead of
writeToFile:atomically:
but you need to create all the subdirectories in the path prior to doing the write. Like this:
// if the directory does not exist, create it...
if ( [fileManager fileExistsAtPath:dir_path] == NO ) {
if ( [fileManager createDirectoryAtPath:dir_path withIntermediateDirectories:NO attributes:NULL error:&error] == NO ) {
NSLog(#"createDirectoryAtPath failed %#", error);
}
}

Resources