NSScanner

  • Hallo Leute,

    ich will mit NSScanner spezifische Einträge aus einer Textdatei auslesen.

    Dazu habe ich folgenden Code gebaut. Beim Kompilieren gibt er mir keinen Fehler aus. Allerdings zeigt er dann den gewünschten String nicht im TextView an.

    Irgendwelche Ideen?



    myScanner = [NSScanner scannerWithString:importlog];
    while (![myScanner isAtEnd])
    {
    NSString *created, *software, *version;

    {
    [myScanner scanString:@"#Log File Created On:" intoString:nil];
    [myScanner scanCharactersFromSet:letterset intoString:&created];
    [myScanner scanString:@"#Software:" intoString:nil];
    [myScanner scanCharactersFromSet:letterset intoString:&software];
    [myScanner scanString:@"#Version:" intoString:nil];
    [myScanner scanCharactersFromSet:letterset intoString:&version];
    [theTextView setString:created];
    }
    }



    Hier einen Hinweis auf den Fehler:

    Quellcode

    1. 2003-09-12 18:34:43.497 StreamloganalyzerIII[629] *** +[NSCell invertedSet]: selector not recognized
    2. 2003-09-12 18:34:43.536 StreamloganalyzerIII[629] *** +[NSCell invertedSet]: selector not recognized
  • Ja :D

    k, wär fies, wnen ich jetzt nur auf die Frage antworten würde, deshalb mal ein bissel mehr: Du musst die Strings initialisieren also am Anfang noch

    Quellcode

    1. created = @"";
    2. software = @"";
    3. version = @"";

    einbauen. Dann sollte es gehen,

    Max
  • Ich glaube nicht, dass es an der Initialisierung liegt. Und wenn schon initialisieren, dann bitte so:

    Quellcode

    1. created = [[NSString alloc] init];
    2. software = [[NSString alloc] init];
    3. version = [[NSString alloc] init];

    Die andere Methode weist den Variablen konstante Strings zu, deren Speicher nicht freigegeben wird.

    Es wäre mal interessant, wie so'n zu scannender String aussieht, was rauskommen soll und was jetzt raus kommt.

    Michael

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Michael ()

  • Ehe ich mir was im Debugger anzeigen kann, steigt der Debugger aus:

    Quellcode

    1. 2003-09-12 19:41:16.875 StreamloganalyzerIII[933] *** +[NSCell invertedSet]: selector not recognized
    2. 2003-09-12 19:41:16.904 StreamloganalyzerIII[933] *** +[NSCell invertedSet]: selector not recognized



    Verstehe ich nicht.
  • Aha, es kommt also gar nix. Ich würde mal nachgucken, ob Du den NSCharacterSet korrekt erzeugst. Scheint mir fast so, als ob da eine Message an das falsche Objekt geschickt wird. Wenn Du da nix feststellen kannst, dann zeig' mal den Code, wo Du den NSCharacterSet erzeugst.

    Du arbeitest bestimmt viel mit id (in den Nibs), oder? ;)

    Michael
  • Ich initialisiere nur ein

    Quellcode

    1. NSCharacterSet *letterset;


    Danach kommt das:

    Quellcode

    1. myScanner = [NSScanner scannerWithString:importlog];
    2. while (![myScanner isAtEnd])
    3. {
    4. {
    5. [myScanner scanString:@"#Log File Created On:" intoString:nil];
    6. [myScanner scanCharactersFromSet:letterset intoString:&created];
    7. [myScanner scanString:@"#Software:" intoString:nil];
    8. [myScanner scanCharactersFromSet:letterset intoString:&software];
    9. [myScanner scanString:@"#Version:" intoString:nil];
    10. [myScanner scanCharactersFromSet:letterset intoString:&version];
    11. [outputString appendString:created];
    12. [outputString appendString:software];
    13. [outputString appendString:version];
    14. [ipAdressView setString:outputString];
    15. }
    16. }
    Alles anzeigen


    Und im Nib File steht zu jedem Outlet die entsprechende Klasse.
  • Original von kay
    Ich initialisiere nur ein

    Quellcode

    1. NSCharacterSet *letterset;

    Nur das? Das ist keine vollständige Initialisierung, sondern eine reine Variablendeklaration. Der Pointer kann sonst wo hin zeigen.
    Die Initialisierung muss etwa so aussehen:

    Quellcode

    1. NSCharacterSet *letterset = [NSCharacterSet letterCharacterSet];

    Michael
  • Jup, definitiv am Characterset oder im Umgang mit der Klasse NSCharacterSet, denn die Methode -invertedSet gehört zur Klasse NSCharacterSet. Dabei fällt mir jetzt auf, nach der Fehlermeldung zu urteilen, wird -invertedSet an eine Klasse geschickt. -invertedSet ist aber eine Instanz-Methode, muss also an eine Instanz von NSCharacterSet geschickt werden.

    Michael
  • Also....ich schildere jetzt nochmal mein vorgehen.

    Ich habe ein Klasseninterface eines AppControllers.

    In diesem Appcontroller hole ich mir ein Textfile und schreibe es in einen String. Danach deklariere ich eine NSScanner und eine NSCharacterset Variable. Etwa so:

    Quellcode

    1. NSScanner *myScanner;
    2. NSCharacterSet *letterset;
    3. myScanner = [NSScanner scannerWithString:importlog];
    4. letterset = [NSCharacterSet characterSetWithCharactersInString:@";"];


    Die App kompiliert ohne Probleme...Nur crashed sie, nachdem ich das File geladen habe.
  • ist die variable importlog sicher?

    vielleicht kannst du mal ein sample machen, in den u einfach den ganzen code postest oder auch einfac hier postest. Und da fällt mir ein: könntest du bei den Anhängen als dateitypen auch noch sit und sitx erlauben? (wer packt denn schon freiwillig zip ;)).

    Max
  • Was verstehst Du unter sicher? sit, dmg, sitx gehen jetzt auch. Danke für den Hinweis. :D

    Also: AppController.h

    Quellcode

    1. @interface AppController : NSObject
    2. {
    3. IBOutlet NSTextField *moreInfoView;
    4. IBOutlet NSTableView *tableView;
    5. IBOutlet NSTextView *theTextView;
    6. IBOutlet NSTextView *ipAdressView;
    7. }
    8. - (IBAction)analyzeLogfile:(id)sender;
    9. - (IBAction)exportLogfile:(id)sender;
    10. - (IBAction)loadLogfile:(id)sender;
    11. @end
    Alles anzeigen


    AppController.m

    Quellcode

    1. @implementation AppController
    2. - (IBAction)loadLogfile:(id)sender
    3. {
    4. NSOpenPanel *openpanel = [NSOpenPanel openPanel];
    5. NSArray *files;
    6. NSScanner *myScanner;
    7. NSCharacterSet *letterset;
    8. NSString *importlog, *created, *software, *version;
    9. NSMutableString *outputString;
    10. NSArray *types=[NSArray arrayWithObjects:@"log",nil];
    11. [openpanel setCanChooseDirectories:TRUE];
    12. [openpanel setCanChooseFiles:TRUE];
    13. [openpanel setAllowsMultipleSelection:TRUE];
    14. [openpanel runModalForTypes:types];
    15. files=[openpanel filenames];
    16. if(files==nil)
    17. {
    18. NSLog(@"no file selected");
    19. }
    20. else
    21. {
    22. importlog=[NSString stringWithContentsOfFile:[files objectAtIndex:0]];
    23. // [theTextView setString:importlog];
    24. myScanner = [NSScanner scannerWithString:importlog];
    25. letterset = [NSCharacterSet characterSetWithCharactersInString:@";"];
    26. while (![myScanner isAtEnd])
    27. {
    28. {
    29. [myScanner scanString:@"#Log File Created On:" intoString:nil];
    30. [myScanner scanCharactersFromSet:letterset intoString:&created];
    31. [myScanner scanString:@"#Software:" intoString:nil];
    32. [myScanner scanCharactersFromSet:letterset intoString:&software];
    33. [myScanner scanString:@"#Version:" intoString:nil];
    34. [myScanner scanCharactersFromSet:letterset intoString:&version];
    35. [outputString appendString:created];
    36. [outputString appendString:software];
    37. [outputString appendString:version];
    38. NSLog(outputString);
    39. [ipAdressView setString:outputString];
    40. }
    41. }
    42. }
    43. }
    44. - (IBAction)analyzeLogfile:(id)sender
    45. {
    46. }
    47. - (IBAction)exportLogfile:(id)sender
    48. {
    49. }
    50. @end
    Alles anzeigen



    Thats it.
  • Na, nun ist mir klar, warum das Programm crashed. Dein letterset besteht ja nur aus einem ';' und in der while-Schleife (die unnötigerweise doppelt eingeklammert ist;)) scannst Du dann eben nur nach Semikolons. In dem Bereich, wo Du scannst, gibt es aber keine Semikolons und deshalb werden auch von den Scanfunktionen Deine Stringvariablen nicht verändert. Da Du diese Variablen vorher nicht mit einem richtigen Objekt 'versehen' hast, kommt es dann beim Anhängen an 'outputString' zum Crash.

    Michael
  • RE: ginge das nicht einfacher?

    SIEHSTE! Hatte doch recht mit der Initialisierung ;) Und auch so, wie ich es hatte. Ist lange her, dass ich das gemacht hab, aber im Unerbewusstsein war's doch richtig :P

    naja, nee. NSScanner hat den vorteil, dass du im prinzip unabhängig von den Zeilenenden bist und auch wesentlich einfacher multi-line einträge verarbeiten kannst. Außerdem geht es so leichter, z.B. über PlugIns viele verschiedene Log-File-Typen zuzulassen. @kay: bleib mal fein dabei.

    Max
  • RE: ginge das nicht einfacher?

    Die Initialisierung ist verhindert nur den Absturz. Den kann man aber auch anders verhindern, in dem man den Rückgabewert von -scanCharactersFromSet:intoString: (YES oder NO) auswertet. Das beim Scanvorgang nix raus kommt, liegt einfach am falschen NSCharacterSet.
    Das ganze ist halt nicht sehr fehlertolerant programmiert. :HW:

    Michael