简体   繁体   English

如何使 NSOutputStream 重定向到标准 output?

[英]How to make NSOutputStream redirect to standard output?

I was wondering what's the best way to make NSOutputStream redirect to standard output.我想知道将NSOutputStream重定向到标准 output 的最佳方法是什么。 The technique I am using right now is to use an output stream that writes to memory, get its data and print that to stdout:我现在使用的技术是使用 output stream 写入 memory,获取其数据并将其打印到标准输出:

  NSOutputStream *stream = [[NSOutputStream alloc] initToMemory];
  [stream open];
  // calls to stream's -write:maxLengh:
  NSData *data = [stream propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
  NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  printf("%s", [string UTF8String]);
  [stream close];

Is there a better way to achieve this?有没有更好的方法来实现这一目标? Specifically, I am not happy about two things with this approach:具体来说,我对这种方法的两件事不满意:

  1. The need for extra memory for data that is written to stream写入 stream 的数据需要额外的 memory

  2. This stream is not reusable -- after I have retrieved data from this stream via [stream propertyForKey:NSStreamDataWrittenToMemoryStreamKey] , the stream is not "reset" ie I want subsequent calls to this method to give me only new data, but its not the case. This stream is not reusable -- after I have retrieved data from this stream via [stream propertyForKey:NSStreamDataWrittenToMemoryStreamKey] , the stream is not "reset" ie I want subsequent calls to this method to give me only new data, but its not the case . This means that I have to create a new NSOutputStream after every time I write to stdout.这意味着我每次写入标准输出后都必须创建一个新的 NSOutputStream。

It doesn't appear there's a built-in way to do this.似乎没有内置的方法可以做到这一点。 If you can use NSFileHandle instead of NSOutputStream , you can use [NSFileHandle fileHandleWithStandardOutput] .如果您可以使用NSFileHandle而不是NSOutputStream ,则可以使用[NSFileHandle fileHandleWithStandardOutput] If you have to use NSOutputStream , try something like this:如果您必须使用NSOutputStream ,请尝试以下操作:

// untested!
@interface FileHandleOutputStream : NSOutputStream
+ (FileHandleOutputStream *)outputStreamWithFileHandle:(NSFileHandle *)fileHandle;
- (id)initWithFileHandle:(NSFileHandle *)fileHandle;
@end

@implementation FileHandleOutputStream {
    NSFileHandle *_fileHandle;
}
+ (FileHandleOutputStream *)outputStreamWithFileHandle:(NSFileHandle *)fileHandle {
    return [[[self alloc] initWithFileHandle:fileHandle] autorelease];
}
- (id)initWithFileHandle:(NSFileHandle *)fileHandle {
    if (self = [super init]) {
        _fileHandle = [fileHandle retain];
    }
    return self;
}
- (void)dealloc {
    [_fileHandle release];
    [super dealloc];
}
- (BOOL)hasSpaceAvailable {
    return YES;
}
- (NSInteger)write:(const uint8_t *)buffer maxLength:(NSUInteger)length {
    [_fileHandle writeData:[NSData dataWithBytesNoCopy:buffer
                                                length:length
                                          freeWhenDone:NO]];
    return length;
}

Now use现在使用

FileHandleOutputStream *myStrem = [FileHandleOutputStream outputStreamWithFileHandle:
                                   [NSFileHandle fileHandleWithStandardOutput]];

Jason Sikes had it almost correct. Jason Sikes几乎是正确的。

There's no need for Cocoa to provide its own constructor here because stdout is available as a "file." Cocoa 无需在此处提供自己的构造函数,因为标准输出可作为“文件”使用。 This doesn't seem to be documented, unfortunately, but works very well:不幸的是,这似乎没有记录在案,但效果很好:

NSOutputStream *outputStream =
    [NSOutputStream outputStreamToFileAtPath:@"/dev/stdout"
                                      append:NO];

You can do the same thing with stderr as well (or use a NSInputStream for stdin).您也可以使用 stderr 做同样的事情(或使用NSInputStream作为标准输入)。

You can also open a NSOutputStream to stdout using "/dev/tty" as the file.您还可以使用“/dev/tty”作为文件打开一个 NSOutputStream 到标准输出。 ("/dev/tty" is the Unix designation for standard input and output.) (“/dev/tty”是标准输入和 output 的 Unix 名称。)

Thus you can create a NSOutputStream to standard out with:因此,您可以创建一个 NSOutputStream 以标准输出:

NSOutputStream *stream = [NSOutputStream outputStreamToFileAtPath: @"/dev/tty"
                                                           append: NO];

A drawback is that this won't work if you run your program within Xcode;一个缺点是,如果您在 Xcode 中运行程序,这将不起作用; you'll have to run it in a terminal window.您必须在终端 window 中运行它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM