Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make NSOutputStream redirect to standard output?

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.

like image 975
Chaitanya Gupta Avatar asked Aug 15 '11 05:08

Chaitanya Gupta


1 Answers

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]];
like image 187
jtbandes Avatar answered Nov 11 '22 08:11

jtbandes