NSFileHandle fileHandleForWritingAtPath: return null!
Asked Answered
P

3

37

my iPad app has a small download facility, for which I want to append the data using an NSFileHandle. The problem is the creation call only returns null file handles. What could be the problem? Here is the three lines of code that are supposed to create my file handle:

NSString *applicationDocumentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
self.finalPath = [applicationDocumentsDirectory stringByAppendingPathComponent: self.fileName]; 
NSFileHandle *output = [NSFileHandle fileHandleForWritingAtPath:self.finalPath];

I checked the file path, and I could see nothing wrong.

TYIA

Pero answered 8/9, 2010 at 3:1 Comment(0)
F
88

fileHandleForWritingAtPath is not a “creation” call. The documentation explicitly states: “Return Value: The initialized file handle, or nil if no file exists at path” (emphasis added). If you wish to create the file if it does not exist, you’d have to use something like this:

 NSFileHandle *output = [NSFileHandle fileHandleForWritingAtPath:self.finalPath];
 if(output == nil) {
      [[NSFileManager defaultManager] createFileAtPath:self.finalPath contents:nil attributes:nil];
      output = [NSFileHandle fileHandleForWritingAtPath:self.finalPath];
 }

If you want to append to the file if it already exists, use something like [output seekToEndOfFile]. Your complete code would then look as follows:

 NSString *applicationDocumentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
 self.finalPath = [applicationDocumentsDirectory stringByAppendingPathComponent: self.fileName]; 
 NSFileHandle *output = [NSFileHandle fileHandleForWritingAtPath:self.finalPath];
 if(output == nil) {
      [[NSFileManager defaultManager] createFileAtPath:self.finalPath contents:nil attributes:nil];
      output = [NSFileHandle fileHandleForWritingAtPath:self.finalPath];
 } else {
      [output seekToEndOfFile];
 }
Fictile answered 17/9, 2010 at 13:15 Comment(1)
My file exist at "/var/mobile/Containers/Data/Application/E914726C-34B7-4B92-A740-90E31131D75E/Library/Caches/" but i am still getting nil.Bounce
W
0

Get documents directory path

+(NSURL *)getDocumentsDirectoryPath
{
    return [[[NSFileManager defaultManager]URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]lastObject];
}

Save text to end of the file

if file doesnt exist create it and write data

+(void)saveText:(NSString *)textTobeSaved atPath:(NSString*)fileName
{
    NSString *filePath = [NSString stringWithFormat:@"%@.text",fileName];
    
    NSString *path = [[self getDocumentsDirectoryPath].path
                      stringByAppendingPathComponent:filePath];
    NSFileHandle *fileHandler = [NSFileHandle fileHandleForWritingAtPath:path];
    if(fileHandler == nil) {
        [[NSFileManager defaultManager] createFileAtPath:path contents:nil attributes:nil];
        fileHandler = [NSFileHandle fileHandleForWritingAtPath:path];
    } else {
        textTobeSaved = [NSString stringWithFormat:@"\n-----------------------\n %@",textTobeSaved];
        [fileHandler seekToEndOfFile];
    }
    
    [fileHandler writeData:[textTobeSaved dataUsingEncoding:NSUTF8StringEncoding]];
    [fileHandler closeFile];
}

get text from file with specified filename

+(NSString *)getTextFromFilePath:(NSString *)fileName
{
    NSString *filePath = [NSString stringWithFormat:@"%@.text",fileName];
    
    NSString *path = [[self getDocumentsDirectoryPath].path
                      stringByAppendingPathComponent:filePath];
    NSLog(@"%@",path);
    if(path!=nil)
    {
    NSString *savedString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
    
    return savedString;
  }else{
    return @"";
  } 
}

Delete file

+(void)deleteFile:(NSString *)fileName
{
    NSString *filePath = [NSString stringWithFormat:@"%@.text",fileName];
    
    NSString *path = [[self getDocumentsDirectoryPath].path
                      stringByAppendingPathComponent:filePath];
    
    NSFileHandle *fileHandler = [NSFileHandle fileHandleForWritingAtPath:path];
    if(fileHandler != nil) {
        [[NSFileManager defaultManager]removeItemAtPath:path error:nil];
    }
    
}
Walkin answered 2/11, 2017 at 9:2 Comment(0)
S
0

The initialiser APIs have changed, but this still might be useful for other people. I was using the FileHandle(forReadingAtPath: String) initialiser, when I realised that:

  • The initialiser returned nil while using fileURL.absoluteString for the path (absolute string looks like file:///Users/xyz/Library/.../Containers/Data/Application/...file.MP4
  • The initialiser worked correctly using fileURL.relativePath for the path. (relative path looks like /Users/xyz/Library/.../Containers/Data/Application/...file.MP4)

Basically, the FileHandler initialiser prefers the relative path over the absolute string.

Serpentiform answered 21/3, 2023 at 5:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.