在Cocoa中将stdout重定向到NSTextView的最佳方法是什么?

时间:2010-03-09 02:09:43

标签: cocoa subprocess stdout

嗨:我想将stdout重定向到NSTextView。这也适用于子流程的输出吗?什么是实现这一目标的最佳方式?

修改 根据Peter Hosey的回答,我实施了以下内容。但我没有得到通知。我做错了什么?

NSPipe *pipe = [NSPipe pipe];
NSFileHandle *pipeHandle = [pipe fileHandleForWriting];
dup2(STDOUT_FILENO, [pipeHandle fileDescriptor]);
NSFileHandle *fileHandle = [[NSFileHandle alloc] initWithFileDescriptor:pipeHandle];
[fileHandle acceptConnectionInBackgroundAndNotify];

NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter];
[dnc addObserver:self selector:@selector(handleNotification:) name:NSFileHandleConnectionAcceptedNotification object:fileHandle];

4 个答案:

答案 0 :(得分:12)

我当时也想做同样的事情并且发现了这篇文章。阅读本文和Apple的文档之后,我能够弄明白。我在这里包括我的解决方案。在接口中声明“pipe”和“pipeReadHandle”。在init方法中,我包含以下代码:

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] ;

handleNotification:方法是

[pipeReadHandle readInBackgroundAndNotify] ;
NSString *str = [[NSString alloc] initWithData: [[notification userInfo] objectForKey: NSFileHandleNotificationDataItem] encoding: NSASCIIStringEncoding] ;
// Do whatever you want with str 

答案 1 :(得分:5)

  

我想将stdout重定向到NSTextView。

你自己的stdout?

  

这也可以用于子流程的输出吗?

不确定

  

实现这一目标的最佳方法是什么?

文件描述符是你的朋友。

创建一个管道(使用NSPipe或pipe(2))和dup2将其写入结束到STDOUT_FILENO。调用子进程时,不要设置它们的标准输出;他们会继承你的标准输出,这是你的管道。 (你可能想关闭子进程中的读取结束。我不确定这是否有必要;尝试并找出答案。如果结果确实如此,你需要使用{{1} }和fork,并在两者之间关闭读取结束。)

使用exec或NSFileHandle异步读取后台管道的读取端。当新数据进入时,使用某种编码对其进行解释并将其附加到文本视图的内容中。

如果文本视图位于滚动视图中,则应在追加之前检查滚动位置。如果它在最后,你可能希望在追加后将其跳回到最后。

答案 2 :(得分:2)

看看PseudoTTY.app

答案 3 :(得分:0)

对于iOS,使用stderr而不是stdout。

NSPipe *pipe = [NSPipe pipe];
pipeHandle = [pipe fileHandleForReading];
dup2([[pipe fileHandleForWriting] fileDescriptor], fileno(stderr));

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

-(void)handleNotification:(NSNotification *)notification{

    [pipeHandle readInBackgroundAndNotify] ;
    NSString *str = [[NSString alloc] initWithData: [[notification userInfo] objectForKey: NSFileHandleNotificationDataItem] encoding: NSASCIIStringEncoding] ;

}