This is the code I use to read from a compressed resource file and write the decompressed data to a file in the documents directory:
- (void)setupPFile
{
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString* passwordsFile = [documentsPath stringByAppendingPathComponent:#"p.txt"];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:passwordsFile];
if (!fileExists) {
NSString *resourceDictPass = DICTIONARY_FILE;
NSString *resourcePath = [[NSBundle mainBundle] pathForResource:resourceDictPass ofType:#"gz"];
NSData *fileCompressedData= [NSData dataWithContentsOfFile:resourcePath];
NSError *error = nil;
[fileCompressedData writeInflatedToFile:passwordsFile error:&error];
if (error) {
NSLog(#"error uncompressing passwords file");
return;
}
}
});
}
This is the error I get:
Printing description of error:
Error Domain=se.bitba.ZlibErrorDomain Code=2 "The operation couldn’t be completed. (se.bitba.ZlibErrorDomain error 2.)"
I am using a NSData+zlib category I found recommended around here.
How to debug this?
Related
I try to get my file in my self created Directory in the Documents Directory into a NSData Object like this:
NSString *path = [documentsDirectory stringByAppendingFormat:#"%#%#",#"/",fileName];
NSError* errorr = nil;
NSData *fileData = [NSData dataWithContentsOfFile:path options: 0 error: &errorr];
if (fileData == nil)
{
NSLog(#"Failed to read file, error %#", errorr);
}
else
{
}
But i always get this error:
Failed to read file, error Error Domain=NSCocoaErrorDomain Code=257 "The operation couldn’t be completed. (Cocoa error 257.)" UserInfo=0x156be110 {NSFilePath=/var/mobile/Applications/679253E3-652C-45EE-B589-609E52E4E3B0/Documents/upload/test.xml, NSUnderlyingError=0x156ba7f0 "The operation couldn’t be completed. Permission denied"}
So if i check if the file is readable:
if ([[NSFileManager defaultManager] isReadableFileAtPath: path] == YES)
NSLog (#"File is readable");
else
NSLog (#"File is read only");
i get the result that the file is readable, so why do i get the error if i want to parse that file into NSData?!
UPDATE: i created my file like this:
NSString *filePath = [self dataFilePath:fileName];
[xmlData writeToFile:filePath atomically:YES];
- (NSString *)dataFilePath: (NSString *) path {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"upload"];
NSError *error = nil;
if (![[NSFileManager defaultManager] fileExistsAtPath:documentsDirectory])
[[NSFileManager defaultManager] createDirectoryAtPath:documentsDirectory withIntermediateDirectories:NO attributes:nil error:&error];
NSString *documentsPath = [documentsDirectory
stringByAppendingPathComponent:path];
return documentsPath;
}
UPDATE2: After creating the file, i move it into another Directory with this function:
- (void)moveXmlFilesToUploadDirectory
{
#try {
//Check if FILES_DIR exists
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:FILES_DIR];//filesDir
NSString *uploadDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:UPLOAD_DIR];//filesDir
if ([[NSFileManager defaultManager] fileExistsAtPath:documentsDirectory])
{
NSString *extension = #"xml";
NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectory error:NULL];
NSEnumerator *e = [contents objectEnumerator];
NSString *filename;
while ((filename = [e nextObject])) {
if ([[filename pathExtension] isEqualToString:extension]) {
[[NSFileManager defaultManager] moveItemAtPath:documentsDirectory toPath:[uploadDirectory stringByAppendingPathComponent:filename] error:NULL];
}
}
}
}
#catch (NSException *exception) {
}
#finally {
}
}
Maybe the Problem is after moving the file! Cause if i try to get my file into a NSData before i move it, everything works...
It seems that you try to copy the whole directory to a destination meant to be a file. The result is that the filepath is a directory path in the end so you can't open it like a file which leads to the permission error message.
You should update your copy code to
while ((filename = [e nextObject])) {
if ([[filename pathExtension] isEqualToString:extension]) {
[[NSFileManager defaultManager] moveItemAtPath:[documentsDirectory stringByAppendingPathComponent: filename] toPath:[uploadDirectory stringByAppendingPathComponent:filename] error:NULL];
}
}
to copy every file individually. That will create than the actual file at the destination path intend of a directory.
The chances are high that you don't have the right permissions for that file. Please check the permissions and add read access for the current user or "everyone". You can set the read permissions for your user by the info dialog (cmd + i) or in the terminal with chmod u+r test.xml. Eventually you have to set the owner before with
sudo chown yourusername test.xml
Hope that makes sense.
I am trying to copy a file from one folder to another folder in documents directory like this:
- (void)saveFile:(NSString *)folderPath
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:#"destination.png"];
NSError *error = nil;
NSString *srcPath = [folderPath stringByAppendingPathComponent:#"filename.png"];
BOOL success = [[NSFileManager defaultManager] copyItemAtPath:srcPath toPath:documentsDirectory error:&error];
if (error)
{
NSLog(#"%#",error);
}
if (success == YES)
{
NSLog(#"Copied");
}
else
{
NSLog(#"Not Copied");
}
}
When i log error, it gives me the following message:
Error Domain=NSCocoaErrorDomain Code=516 "The operation couldn’t be completed. (Cocoa error 516.)" UserInfo=0x9d665a0 {NSUserStringVariant=(
Move
), NSFilePath=/Users/username/Library/Application Support/iPhone Simulator/5.1/Applications/BC37C9D7-7995-47C1-8131-2B07BADCBECB/Documents/foldername/B713320C-2CA0-4FD3-93F6-71D76B102B83/src.png, NSDestinationFilePath=/Users/username/Library/Application Support/iPhone Simulator/5.1/Applications/BC37C9D7-7995-47C1-8131-2B07BADCBECB/Documents, NSUnderlyingError=0x9d41c60 "The operation couldn’t be completed. File exists"}
Issue 1:
The issue occurred because, the directory already contains a file with same file name.
You should check whether the file exist in the folder or not like:
- (void)saveFile:(NSString *)folderPath
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:#"destination.png"];
NSError *error = nil;
NSString *srcPath = [folderPath stringByAppendingPathComponent:#"filename.png"];
if ([[NSFileManager defaultManager] fileExistsAtPath:dataPath])
{
//removing file
if (![[NSFileManager defaultManager] removeItemAtPath:dataPath error:&error])
{
NSLog(#"Could not remove old files. Error:%#",error);
}
}
BOOL success = [[NSFileManager defaultManager] copyItemAtPath:srcPath toPath:dataPath error:&error];
if (success == YES)
{
NSLog(#"Copied");
}
else
{
NSLog(#"Not Copied %#", error);
}
}
Issue 2:
You must provide a file name not a directory.
Replace:
BOOL success = [[NSFileManager defaultManager] copyItemAtPath:srcPath toPath:documentsDirectory error:&error];
With:
BOOL success = [[NSFileManager defaultManager] copyItemAtPath:srcPath toPath:dataPath error:&error];
copyItemAtPath: is giving error as that file is already exist in that location. So you should do this before you copy file.
if ([[NSFileManager defaultManager] fileExistsAtPath: srcPath])
[[NSFileManager defaultManager] removeItemAtPath: srcPath error:nil];
Replace this line:
BOOL success = [[NSFileManager defaultManager] copyItemAtPath:srcPath toPath:documentsDirectory error:&error];
With:
BOOL success = [[NSFileManager defaultManager] copyItemAtPath:srcPath toPath:dataPath error:&error];
Below is the Code:
NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
[imageData writeToFile:savedImagePath options:NSDataWritingAtomic error:&error];
if(error != nil)
NSLog(#"write error %#", error);
error:
write error Error Domain=NSCocoaErrorDomain Code=4 "The operation couldn’t be completed. (Cocoa error 4.)" UserInfo=0x8b7b850 {NSUnderlyingError=0x8b7d7c0 "The operation couldn’t be completed. No such file or directory", NSFilePath=/Users/alfa-1/Library/Application Support/iPhone Simulator/6.0/Applications/C24B228A-599E-4249-97A7-17775E8A546B/Library/Caches/ChannelListImages/http:/direct.domain.com/files/icons/1-all-cb.jpg, NSUserStringVariant=Folder}
Before writing the data to file. You need to create the folder. follow these steps
#define APPLICATION_DATA_DIRECTORY #"Application Data"
+ (NSString *)cachesDirectoryPath
// Returns the path to the caches directory. This is a class method because it's
// used by +applicationStartup.
{
NSString * result;
NSArray * paths;
result = nil;
paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
if ( (paths != nil) && ([paths count] != 0) ) {
assert([[paths objectAtIndex:0] isKindOfClass:[NSString class]]);
result = [paths objectAtIndex:0];
}
result = [result stringByAppendingPathComponent:APPLICATION_DATA_DIRECTORY];
if (![[NSFileManager defaultManager] fileExistsAtPath:result]) {
[[NSFileManager defaultManager] createDirectoryAtPath:result withIntermediateDirectories:YES attributes:nil error:NULL];
}
return result;
}
after this: #define kPhotosDirectoryName #"ApplicationDocuments"
NSMutableString *savePath = [NSMutableString string];
[savePath appendFormat:#"%#/%#",[YOURClass cachesDirectoryPath],kPhotosDirectoryName];
[savePath appendFormat:#"/%#",YOUR_FILE_NAME];
if (![[NSFileManager defaultManager] fileExistsAtPath:savePath]) {
//write the data to file here
}
Try this sample. It works for me.
Declare -(NSString*) datafilepath in .h file
-(NSString *) datafilepath{
NSArray *path=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documents=[path objectAtIndex:0];
return [documents stringByAppendingFormat:#"/sample.plist"];
}
Anywhere u want to perform write function
NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
[imageData writeToFile:[self datafilepath]atomically:YES];
if(error != nil)
NSLog(#"write error %#", error);
Hope this helps!!!
I want use writeToFile to store a pic image to the documents, but find the error below, how to solve it ?
Error Domain=NSCocoaErrorDomain Code=512 "The operation couldn’t be completed. (Cocoa error 512.)" {NSFilePath=/Users/alexqdh/Library/Application Support/iPhone Simulator/6.0/Applications/xxx/Documents/girl.png, NSUnderlyingError=0x753e630 "The operation couldn’t be completed. Is a directory"}
-(NSString*)getImagePath:(NSString *)name
{
NSArray *path =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [path objectAtIndex:0];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *finalPath = [docPath stringByAppendingPathComponent:name];
[fileManager createDirectoryAtPath:finalPath withIntermediateDirectories:YES attributes:nil error:nil];
return finalPath;
}
//below is how to use NSData writeToFile
AFImageRequestOperation *opera = [AFImageRequestOperation imageRequestOperationWithRequest:request imageProcessingBlock:nil
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
img.image = image;
[self.view addSubview:img];
NSData *imageData = UIImagePNGRepresentation(img.image);
if(imageData == nil)
{
NSLog(#"imageData nil");
}
NSString *picPath = [self getImagePath:#"girl.png"];
NSLog(#"path:%#",picPath);
NSError *error = [[NSError alloc]init];
BOOL a = [imageData writeToFile:picPath options:NSDataWritingAtomic error:&error];
if(a == YES)
{
NSLog(#"YES");
}
else
{
NSLog(#"NO.error:%#", error);
}
/*NSData *imageData = UIImagePNGRepresentation(img.image);
NSString *picPath = [self getImagePath:#"girl.png"];
[imageData writeToFile:picPath atomically:YES];*/
NSLog(#"Got it.code:%d",response.statusCode);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
NSLog(#"Failed pic.error:%#",error);
}];
[opera start];
The problem is caused by creating a directory with the name of the image, then trying to write a file in place of the directory. In other words, you are first creating a directory named:
Documents/girl.png/
then you try to write a file to the path:
Documents/girl.png
Obviously this is not what you meant to do. In your getImagePath: method, get rid of the call to create the directory. The Documents directory will already exist. And of course you don't want a directory corresponding to the filename.
One other option is to change your getImagePath: to:
- (NSString*)getImagePath:(NSString *)name {
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [path objectAtIndex:0];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *finalPath = [docPath stringByAppendingPathComponent:name];
// Remove the filename and create the remaining path
[fileManager createDirectoryAtPath:[finalPath stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil];
return finalPath;
}
This updated code now supports you passing in name values that include subdirectories you might want.
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);
}
}