如何使 NSOutputStream 重定向到标准输出?

发布于 2024-11-29 20:48:32 字数 735 浏览 2 评论 0原文

我想知道使 NSOutputStream 重定向到标准输出的最佳方法是什么。我现在使用的技术是使用写入内存的输出流,获取其数据并将其打印到标准输出:

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

是否有更好的方法来实现此目的?具体来说,我对这种方法有两件事不满意:

  1. 写入流的数据需要额外的内存

  2. 此流是不可重用 - 在我通过 [stream propertyForKey:NSStreamDataWrittenToMemoryStreamKey] 从此流中检索数据后,该流不会“重置”,即我希望对此方法的后续调用只提供新数据,但是它不是案件。这意味着每次写入 stdout 后我都必须创建一个新的 NSOutputStream。

I was wondering what's the best way to make NSOutputStream redirect to standard 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:

  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

  2. This stream is not reusable -- after I have retrieved data from this stream via [stream propertyForKey:NSStreamDataWrittenToMemoryStreamKey], the stream is not "reset" i.e. 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦里的微风 2024-12-06 20:48:32

似乎没有内置的方法可以做到这一点。如果您可以使用 NSFileHandle 而不是 NSOutputStream,则可以使用 [NSFileHandle fileHandleWithStandardOutput]。如果您必须使用 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;
}

现在使用

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

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]. If you have to use NSOutputStream, try something like this:

// 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]];
傲影 2024-12-06 20:48:32

Cocoa 不需要在这里提供自己的构造函数,因为 stdout 可以作为“文件”使用。不幸的是,这似乎没有记录,但效果很好:

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

您也可以使用 stderr 执行相同的操作(或使用 NSInputStream 作为 stdin)。

There's no need for Cocoa to provide its own constructor here because stdout is available as a "file." 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).

[旋木] 2024-12-06 20:48:32

您还可以使用“/dev/tty”作为文件打开一个 NSOutputStream 到 stdout。 (“/dev/tty”是标准输入和输出的 Unix 名称。)

因此,您可以创建一个 NSOutputStream 来标准输出:

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

缺点是,如果您在 Xcode 中运行程序,这将不起作用;您必须在终端窗口中运行它。

You can also open a NSOutputStream to stdout using "/dev/tty" as the file. ("/dev/tty" is the Unix designation for standard input and output.)

Thus you can create a NSOutputStream to standard out with:

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

A drawback is that this won't work if you run your program within Xcode; you'll have to run it in a terminal window.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文