2

I am trying to create a small rsync program in Cbjective-C. It presently accesses the terminal command line through an NSTask and reads the command line's output to a string that is displayed in a NSTextField; however, when I use this small program on a very large file (around 8 gb) it does not display the output until after the RSYNC is complete. I want the NSTextField to continually update while the process is running. I have the following code and am looking for ideas!:

 -(IBAction)sync:(id)sender
{
    NSString *sourcePath = self.source.stringValue;
    NSString *destinationPath = self.destination.stringValue;

    NSLog(@"The source is %@. The destination is %@.", sourcePath, destinationPath);

    NSTask *task;
    task = [[NSTask alloc] init];
    [task setLaunchPath:@"/usr/bin/rsync"];

    NSArray *arguments;
    arguments = [NSArray arrayWithObjects: @"-rptWav", @"--progress", sourcePath, destinationPath, nil];
    [task setArguments: arguments];

    NSPipe *pipe;
    pipe = [NSPipe pipe];
    [task setStandardOutput: pipe];

       // [task setStandardInput:[NSPipe pipe]];

    NSFileHandle *file;
    file = [pipe fileHandleForReading];

    [task launch];

    NSData *data;
    data = [file readDataToEndOfFile];

    while ([task isRunning])
    {
        NSString *readString;
        readString = [[NSString alloc] initWithData: data encoding:NSUTF8StringEncoding];

        textView.string = readString;
        NSLog(@"grep returned:\n%@", readString);

    }

    }
crashprophet
  • 327
  • 1
  • 4
  • 13
  • What do you want it to update with? Surely using a progress indicator makes more sense? – trojanfoe Oct 12 '12 at 15:30
  • Basically the rsync occurs and the output occurs in one large batch string after its done. I would like to have the string constantly updating with the percentage completion ect. of the rsync outuput – crashprophet Oct 14 '12 at 04:16
  • Sounds more like an issue with `rsync` than anything to do with the text field. Have you tried passing `--progress` to `rsync`? – trojanfoe Oct 14 '12 at 06:32
  • yeah I use the --progress and it works except the entire output of the rsync is put into a file and it is not read constantly, only once at the very end – crashprophet Oct 15 '12 at 21:09

1 Answers1

0

OK, the issue is with the way in which you are reading the data from the pipe. You are using:

NSData *data = [file readDataToEndOfFile];

Which will read everything written by the child process in one go, up until the pipe closes (when the child process has terminated).

What you need to do is read a character at-at-time and reconstruct the output line. You also want to use non-blocking mode, so that your main UI thread isn't interrupted when there is no data to read (better still, this should be done in a background thread so that the main UI thread remains completely uninterrupted).

trojanfoe
  • 120,358
  • 21
  • 212
  • 242