0

我有一个使用 打印到 stdout 的 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 方法,但您不会喜欢它。这使用了pipe () 和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

我在这个问题中遵循了选定的答案帖子: 在 Cocoa 中将标准输出重定向到 NSTextView 的最佳方法是什么?

跟着我感觉有点熟悉。我为管道和读取处理程序创建了一个 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 回答