Fehler 2 bei NSFileHandle fileHandleForReadingFromURL

anhe

Aktives Mitglied
Thread Starter
Dabei seit
13.11.2007
Beiträge
1.899
Reaktionspunkte
309
Hallo zusammen,

ich beschäftige (lerne) aktuell gerade mit dem öffnen, schliessen, und bearbeiten von Dateien. Mein OS ist OS X 10.11.2 und Xcode 7.2. Bei dem folgenden Minimalbeispiel kommt es zu einem Fehler, wenn ich eine Datei (testfile) auf meinem Synology NAS (mit Apache-Server) mit der Methode fileHandleForReadingFromURL einem FileHandle zuweisen möchte (Die IPdesNAS ist natürlich durch die tatsächliche IP ersetzt):

Code:
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        NSError *myError = nil;
        NSURL *myURL2 = [NSURL URLWithString:@"http://IPdesNAS/~anhe/web/test/testfile"];
        NSFileHandle *inFile = [NSFileHandle fileHandleForReadingFromURL:myURL2 error:&myError];
        NSLog(@"%@", myError);
        NSData *buffer;
       
        if (inFile == nil) {
            NSLog(@"Open of file for reading failed");
            return 1;
        }
       
        buffer = [inFile readDataToEndOfFile];
        [inFile closeFile];
       
        NSString *returnDataFromBuffer = [[NSString alloc]initWithData:buffer encoding:NSUTF8StringEncoding];
       
        NSLog(@"%@", returnDataFromBuffer);

       
    }
    return 0;
}

Hierbei erhalte ich die folgende Ausgabe:

Code:
Error Domain=NSCocoaErrorDomain Code=2 "(null)" UserInfo={NSFilePath=/~anhe/web/test/testfile}
Open of file for reading failed
Program ended with exit code: 1

Um den Fehler einzugrenzen habe ich zwei weitere Minimalbeispiele erstellt.

1.) Die gleiche Datei lokal auf meinem Mac einem FileHandle zugewiesen ergibt keinen Fehler.

Code:
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        NSFileHandle *inFile = [NSFileHandle fileHandleForReadingAtPath:@"/Users/anhe/test/testfile"];
        NSData *buffer;
       
        if (inFile == nil) {
            NSLog(@"Open of file for reading failed");
            return 1;
        }
       
        buffer = [inFile readDataToEndOfFile];
        [inFile closeFile];
        NSString *returnDataFromBuffer = [[NSString alloc]initWithData:buffer encoding:NSUTF8StringEncoding];
       
        NSLog(@"%@", returnDataFromBuffer);
       
    }
    return 0;
}

2.) Eine Datei index.html die unter http://IPdesNAS/~anhe/web/Homepage/ auf dem NAS liegt kann auch ohne Fehler gelesen werden. An der Bereitstellung einer Datei als URL über das NAS mit dem Apache-Server scheint es nicht zu liegen.

Code:
#import <Foundation/Foundation.h> 

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        NSError *myError = nil;
        NSURL *myURL = [NSURL URLWithString:@"http://IPdesNAS/~anhe/web/Homepage/"];
        NSString *myHomePage = [NSString stringWithContentsOfURL:myURL encoding:NSASCIIStringEncoding error:&myError];
        NSLog(@"%@", myError);
        NSLog(@"%@", myHomePage);
       
    }
    return 0;
}

Auf der Apple Developers Seite gibt es eine Auflistung der Error Objects, Domains, and Codes und dort findet sich in der Tabelle 1-1 Part of the POSIX-error code declarations (allerdings für iOS) unter Fehler 2 folgende Angabe:

#define ENOENT 2 /* No such file or directory */

Die Datei ist aber definitiv dort. Könnt Ihr mir helfen?

Ansonsten wünsche ich allen ein paar schöne Urlaubstage

Viele Grüße

André
 
Hallo André,

Du suchst eigentlich/vermutlich NSURLSessionDataTask…

Viele Grüße
 
Hallo little_pixel,

danke für Deine Antwort. Das ist möglich, dass NSURLSessionDataTask das liefert. Ich versuche gerade zu verstehen, wie ich mit NSURLSessionDataTask einem NSData object zuweise. Aber müsste es mit meinem Minimalbeispiel nicht auch funktionieren?

Viele Grüße

André
 
Beispiel, siehe unten.
Denke auch an die "App Transport Security Settings".

Viele Grüße

Code:
-(BOOL)start:(id)sender
{

    // …
   
    NSURL *URL = [NSURL URLWithString:@"https://www.macuser.de/threads/fehler-2-bei-nsfilehandle-filehandleforreadingfromurl.739109/"];
   
    if(URL == nil)
    {
       
        return NO;
       
    }
   
    // …
   
    NSMutableURLRequest *URLRequest = [NSMutableURLRequest requestWithURL:URL
                                                              cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
                                                          timeoutInterval:5.0];
   
    if(URLRequest == nil)
    {
       
        return NO;
       
    }
   
    // …
   
    NSURLSession *URLSession = [NSURLSession sharedSession];
   
    if(URLSession == nil)
    {
       
        return NO;
       
    }
   
    // …
   
    void (^handler)(NSData *data, NSURLResponse *response, NSError *error);
   
    handler = ^(NSData *data, NSURLResponse *response, NSError *error)
    {
       
        // …
       
        if(error != nil)
        {
           
            // …
           
            NSLog(@"%@", error);
           
            // …
           
            return;
           
            // …
           
        }
       
        // …
       
        NSString *string = [[NSString alloc] initWithData:data
                                                 encoding:NSUTF8StringEncoding];
       
        if([string length] < 1)
        {
       
            return;
       
        }
       
        // …
       
        NSLog(@"%@", string);
       
        // …
       
    };
   
    // …
   
    NSURLSessionDataTask *URLSessionDataTask = [URLSession dataTaskWithRequest:URLRequest
                                                             completionHandler:handler];
   
    if(URLSessionDataTask == nil)
    {
       
        return NO;
       
    }
   
    // …
   
    [URLSessionDataTask resume];
   
    // …
   
    return YES;
   
    // …

}
 
Hallo little_pixel,

vielen Dank für Dein Beispiel. Ähnliches hatte ich auch schon erstellt, das lief aber noch nicht. Ich hatte zum Beispiel nicht ein NSMutableURLRequest Object erzeugt. Den Block hatte ich auch schon sogar ähnlich erstellt. Aber ähnlich ist halt auch nur "fast" gleich ...

Leider verwirrt mich das ein wenig und ich brauch ein wenig Zeit um das nachzuvollziehen.

Wichtig für mein Verständnis ist mir aber: Ist mein Minimalbeispiel falsch? Es wäre nett, wenn Du dazu noch mal kurz einen Satz schreiben könntest. Ansonsten weiß ich jetzt nicht, ob ich das gelernte der letzten Tage verstanden habe (wenn meine Lösung grundsätzlich richtig ist) oder aber nicht, weil NSFileHandle fileHandleForReadingFromUrl eben nicht dafür geeignet/gedacht ist.

Viele Grüße

André
 
Hallo nochmal,

zunächst hat es mir keine Ruhe gelassen, warum das wie ich es oben versucht habe nicht funktioniert. Das funktioniert leider immer noch nicht, aber statt den Weg über eine NSFileHandle-Instanz zu gehen und in NSData zu schreiben, schreibe ich nun direkt in ein NSData-Objekt mittels dataWithContentsofURL. Das funktioniert, keine Ahnung warum das mit NSFileHandle fileHandleForReadingFromURL nicht funktioniert.

Code:
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        NSError *myError = nil;
        NSURL *myURL2 = [NSURL URLWithString:@"http://IPdesNAS/~anhe/web/test/testfile"];
        NSData *buffer = [NSData dataWithContentsOfURL:myURL2 options:NSDataReadingMappedAlways error:&myError];
        NSLog(@"%@", myError);
       
        NSString *returnDataFromBuffer = [[NSString alloc]initWithData:buffer encoding:NSUTF8StringEncoding];
       
        NSLog(@"%@", returnDataFromBuffer);
       
    }
    return 0;
}

little_pixel, danke für Deine Mühen auch wenn ich das jetzt nicht so unmittelbar umgesetzt habe!

Viele Grüße

André
 
Für Nachstehendes gibt es wenn und aber…

NSFileHandle ist für lokale Aufgaben.
Du lässt Dich von dem Parameter URL fehlleiten.
Es gibt unterschiedliche Arten von URL. Schaue Dir dazu mal NSURL genauer an.

Apple bietet immer mehr URLs als Parameter an, anstatt "einfache" Pfade, also Text.
Das hat einige Vorteile.

Eine lokale URL beginnt dann mit file:///

Du möchtest aber auf externe Inhalte via http zugreifen.
D.h. Du musst einen Request ausführen.

Es gibt natürlich auch Methoden im Framework, die den Request intern mit Standardwerte ausführen.

Viele Grüße
 
Huch, Du bist aber schnell im Antworten. Bei meiner Antwort steht bei mir aktuell noch "Vor einer Minute" :)

Ja, das stimmt. Ich habe bisher, für mich, immer URL als "http(s), ..." und relative und absolute Pfade unterschieden. Danke für Deine Anmerkungen ich lese mir gleich mal die NSURL Class reference in Xcode an.

Viele Grüße

André
 
Zurück
Oben Unten