iOS Stream Programming Guide -- 流编程指南

1,从输入流中读取:
1) 创建和初始化一个 NSInputStream实例
2)Schedule流对象到一个run loop并打开流
3)处理流对象的事件--使用代理
4)当没有数据可读时,销毁流对象。

1)准备流对象:需要有一个文件,一个NSData 或 一个网络socket
Listing 1  Creating and initializing an NSInputStream object
- (void)setUpStreamForFile:(NSString *)path {
    // iStream is NSInputStream instance variable
    iStream = [[NSInputStream alloc] initWithFileAtPath:path];
    [iStream setDelegate:self];
    [iStream scheduleInRunLoop:[NSRunLoop currentRunLoop]   forMode:NSDefaultRunLoopMode];
    [iStream open];

}

2)处理流事件:
在流对象open之后,你就刻意查看其状态、是否有可用的字节可读和任何原始错误信息等,如下所示:
streamStatus
hasBytesAvailable
streamError

streamStatus
返回的状态是一个 NSStreamStatus常量,指示流是opening、reading,还是到了流的末尾,等等。
streamError返回的错误信息是一个NSError对象,封装了错误发生的位置。
最重要的是,一旦流打开了,他就开始持续发送 stream:handleEvent:消息给其代理,直到其遇到流的末尾。这些消息包括一个参数,是一个 NSStreamEvent常量,用来指示事件类型。对于NSInputStream来说,最常见的事件类型是 NSStreamEventOpenCompletedNSStreamEventHasBytesAvailable,和 NSStreamEventEndEncountered。代理一般最感兴趣 NSStreamEventHasBytesAvailable。下面是一个例子:

Listing 2  Handling a bytes-available event

- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {
 
    switch(eventCode) {
        case NSStreamEventHasBytesAvailable:
        {
            if(!_data) {
                _data = [[NSMutableData data] retain];
            }
            uint8_t buf[1024];
            unsigned int len = 0;
            len = [(NSInputStream *)stream read:buf maxLength:1024];
            if(len) {
                [_data appendBytes:(const void *)buf length:len];
                // bytesRead is an instance variable of type NSNumber.
                [bytesRead setIntValue:[bytesRead intValue]+len];
            } else {
                NSLog(@"no buffer!");
            }
            break;
        }
        // continued


3)销毁流对象:
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
{
    switch(eventCode) {
        case NSStreamEventEndEncountered:
        {
            [stream close];
            [stream removeFromRunLoop:[NSRunLoop currentRunLoop]   forMode:NSDefaultRunLoopMode];
            [stream release];
            stream = nil; // stream is ivar, so reinit it
            break;
        }
        // continued ...
    }
}

二,向输入流写入:
1)创建并初始化一个NSOutputStream,并设置一个代理
2)安排流对象到一个run loop并打开。
3)处理事件
4)如果流对象已经将数据写入内存,通过键NSStreamDataWritenToMemoryStreamKey来获得数据。
5)当没有更多的数据需要写时,销毁流对象。

1)准备流对象:必须给输入流指定一个目标,刻意是一个文件,一个C buffer,应用程序内存,或一个网络socket

创建并初始化输出流到内存的例子:
- (void)createOutputStream {
    NSLog(@"Creating and opening NSOutputStream...");
    // oStream is an instance variable
    oStream = [[NSOutputStream alloc] initToMemory];
    [oStream setDelegate:self];
    [oStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [oStream open];
}

2)在流open之后,你可以获取
streamStatus
hasSpaceAvailable
streamError

状态为一个NSStreamStatus枚举,指示流是opening,writing,流的末尾 等等

代理同样是stream:handleEvent: event也是NSStreamEvent枚举,一半是NSStreamEventOpenCompleted.NSStreamEventHasSpaceAvailable,和NSStreamEventEndEncountered。

Listing 2  Handling a space-available event
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
{
    switch(eventCode) {
        case NSStreamEventHasSpaceAvailable:
        {
            uint8_t *readBytes = (uint8_t *)[_data mutableBytes];
            readBytes += byteIndex; // instance variable to move pointer
            int data_len = [_data length];
            unsigned int len = ((data_len - byteIndex >= 1024) ?
                1024 : (data_len-byteIndex));
            uint8_t buf[len];
            (void)memcpy(buf, readBytes, len);
            len = [stream write:(const uint8_t *)buf maxLength:len];
            byteIndex += len;
            break;
        }
        // continued ...
    }
}

3)销毁流对象;
Listing 3  Closing and releasing the NSInputStream object
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
{
    switch(eventCode) {
        case NSStreamEventEndEncountered:
        {
            NSData *newData = [oStream propertyForKey:
                NSStreamDataWrittenToMemoryStreamKey];
            if (!newData) {
                NSLog(@"No data written to memory!");
            } else {
                [self processData:newData];
            }
            [stream close];
            [stream removeFromRunLoop:[NSRunLoop currentRunLoop]  forMode:NSDefaultRunLoopMode];
            [stream release];
            oStream = nil; // oStream is instance variable
            break;
        }
        // continued ...
    }
}

通过给NSOutputStream对象发送一个propertyForKey:消息,指定键为NSStreamDataWrittenToMemoryStreamKey,可以获得其写入内存的数据,返回一个NSData对象。

三、Polling Versus Run-Loop Scheduling

四、处理流错误

五、Setting up Socket Streams:

http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Streams/Articles/PollingVersusRunloop.html#//apple_ref/doc/uid/20002275-CJBEDDBG
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值