0

を使用して標準出力に出力する C 関数があり、fprintf標準出力の内容を に表示しようとしていUIAlertViewます。私のコードは次のとおりです。

NSFileHandle *stdoutFileHandle = [NSFileHandle fileHandleWithStandardOutput];
NSData *stdoutData = [stdoutFileHandle availableData];
NSString *stdoutString = [[NSString alloc] initWithData:stdoutData encoding:NSASCIIStringEncoding];

UIAlertView *stdoutAlert = [[UIAlertView alloc] initWithTitle:@"STDOUT OUTPUT" message:stdoutString delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[stdoutAlert show];

コードを実行すると、次のエラーが発生します。

キャッチされていない例外 'NSFileHandleOperationException' が原因でアプリを終了しています。理由: '[NSConcreteFileHandle availableData]: 不正なファイル記述子'

に置き換える[stdoutFileHandle availableData]と、同等のエラーが発生し[stdoutFileHandle readDataToEndOfFile]ます。

4

2 に答える 2

4

問題は、出力ストリームから読み取っていることです。これを機能させるには、stdout をだまして、その内容をコンソールではなく入力ストリームに書き込む必要があります。

これを行う古い C の方法は知っていますが、気に入らないでしょう。これはパイプ() とdup2 () を使用します。

int pipefd[2];

pipe(pipefd);
dup2(pipefd[1], STDOUT_FILENO);
close(pipefd[1]);

この時点で、stdout に書き込まれたものはすべて で読み取ることができますpipefd[0]。その時点で、 を使用-initWithFileDescriptor:して から読み取ることができますpipefd[0]

NSFileHandle *stdoutReader = [[NSFileHandle alloc] initWithFileDescriptor:pipefd[0]];

多くのエラーチェックを行う必要があることに注意してください。それが役立つことを願っています。

于 2012-09-02T01:57:48.173 に答える
3

この質問で選択した回答の投稿に従いました: What is the best way to redirect stdout to NSTextView in Cocoa?

私にとっては、従うのが少し親しみやすいように感じました。パイプと読み取りハンドラー用に NSPipe と NSFileHandler オブジェクトを作成し、通知を使用しました。必要に応じて、以下の open メソッドを viewDidAppear および viewDidDisappear メソッドに配置しましたが、適切な場所に配置できます

// Piping stdout info from here WILL NOT PIPE NSLOG:
// https://stackoverflow.com/questions/2406204/what-is-the-best-way-to-redirect-stdout-to-nstextview-in-cocoa
- (void) openConsolePipe {
    _pipe = [NSPipe pipe];
    _pipeReadHandle = [_pipe fileHandleForReading] ;
    dup2([[_pipe fileHandleForWriting] fileDescriptor], fileno(stdout)) ;

    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(handleNotification:) name: NSFileHandleReadCompletionNotification object: _pipeReadHandle] ;
    [_pipeReadHandle readInBackgroundAndNotify] ;
}

- (void) closeConsolePipe {
    if (_pipe != nil) {
        [[_pipe fileHandleForWriting] closeFile];

        // documentation suggests don't need to close reading file handle b/c auto but this suggests otherwise:
        // https://stackoverflow.com/questions/13747232/using-nstask-and-nspipe-causes-100-cpu-usage
//        [[_pipe fileHandleForReading] closeFile];
    }
}

- (void) handleNotification:(NSNotification *)notification {
    [_pipeReadHandle readInBackgroundAndNotify] ;
    NSString *str = [[NSString alloc] initWithData: [[notification userInfo] objectForKey: NSFileHandleNotificationDataItem] encoding: NSUTF8StringEncoding];

    // do what you want with the str here.
    [_consoleView setText:[_consoleView.text stringByAppendingString:str]];
    [_consoleView scrollRangeToVisible:NSMakeRange([_consoleView.text length], 0)];
}

これが他の誰かがこれをグーグルで検索するのに役立つことを願っています...

于 2014-04-06T21:29:55.433 に答える