2011-08-15 23 views
9

मैं सोच रहा था कि NSOutputStream मानक आउटपुट पर रीडायरेक्ट करने का सबसे अच्छा तरीका क्या है।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]; 

वहाँ इस लक्ष्य को हासिल करने के लिए एक बेहतर तरीका है: तकनीक मैं अभी उपयोग कर रहा हूँ, एक निर्गम धारा है कि स्मृति के लिए लिखते हैं का उपयोग अपने डेटा मिलता है और है कि stdout में मुद्रित करने के लिए है? विशेष रूप से, मैं इस दृष्टिकोण के साथ दो चीजों के बारे में खुश नहीं हूँ:

  1. कि

  2. यह स्ट्रीम स्ट्रीम करने के लिए लिखा है डेटा के लिए अतिरिक्त स्मृति के लिए की जरूरत पुन: प्रयोज्य नहीं है - के बाद मैं से डेटा पुनः प्राप्त है यह स्ट्रीम [stream propertyForKey:NSStreamDataWrittenToMemoryStreamKey] के माध्यम से, स्ट्रीम "रीसेट" नहीं है यानी मुझे इस विधि को केवल नए डेटा देने के लिए बाद की कॉल चाहिए, लेकिन यह मामला नहीं है। इसका मतलब यह है कि जब भी मैं stdout लिखता हूं, मुझे हर बार एक नया NSOutputStream बनाना होता है।

उत्तर

11

ऐसा नहीं लगता है कि ऐसा करने के लिए एक अंतर्निहित तरीका है। यदि आप NSOutputStream के बजाय NSFileHandle का उपयोग कर सकते हैं, तो आप [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]]; 
+0

मुझे 'NSFileHandle' के बारे में पता था, लेकिन इसे 'NSOutputStream' के उप-वर्ग के अंदर लपेटना ऐसा कुछ नहीं था जिसे मैंने सोचा था। बहुत दिलचस्प है, और यह निश्चित रूप से काम करना चाहिए। –

+0

जैसे ही मैंने सत्यापित किया है कि यह सही ढंग से काम करता है (मुझे ऐसा कुछ भी नहीं दिख रहा है जो इस के साथ गलत होना चाहिए)। –

+0

यह बहुत अच्छी तरह से काम करता है। एकमात्र चेतावनी जो मैं जोड़ सकता हूं वह यह है कि 'NSOutputStream' विधियों को ओवरराइड करने के अलावा, इसे '-open' या' -close' जैसी कुछ' एनएसएसटीम 'विधियों को ओवरराइड करने की आवश्यकता हो सकती है। सहायता के लिए धन्यवाद। –

-1

का उपयोग तुम भी "/ dev/tty" का उपयोग कर फ़ाइल के रूप में stdout करने के लिए एक NSOutputStream खोल सकते हैं। ("/ Dev/tty" मानक इनपुट और आउटपुट के लिए यूनिक्स पद है।)

इस प्रकार आप के लिए एक NSOutputStream बना सकते हैं के साथ बाहर मानक:

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

एक दोष यह है कि यह करता है, तो काम नहीं करेगा आप एक्सकोड के भीतर अपना प्रोग्राम चलाते हैं; आपको इसे टर्मिनल विंडो में चलाना होगा।

+1

'/ dev/tty' एक प्रक्रिया का नियंत्रण टर्मिनल है, मानक आउटपुट या इनपुट नहीं। यह कहने में असफल हो जाएगा, मैं कहता हूं, मैं एक फ़ाइल में stdout को पुनर्निर्देशित करता हूं। इस मामले में, 'dev/tty' अभी भी टर्मिनल पर आउटपुट दिखाएगा, जो गलत है। –

संबंधित मुद्दे