iosが開発した入力ストリームからデータを読み込む


译文:Reading From Input Streams
ios cocoaプログラミング、NSInputStreamからデータを読み込むには、いくつかのステップがあります.
1.NSInputStreamインスタンスをデータ・ソースから作成および初期化
2.入力ストリームオブジェクトをrun loop,open the streamに構成する
3.ストリームオブジェクトのdelegate関数によるイベントの処理
4.すべてのデータが読み終わると、ストリームオブジェクトのメモリ処理を行う
一、ストリームオブジェクトを使用する準備
NSInputStreamオブジェクトを使用する前に、ストリームのデータソースが必要です.データソースのタイプは、ファイル、NSDataオブジェクト、またはネットワークソケットです.
NSInputStreamの初期化関数およびファクトリメソッドは、NSDataおよびファイルからNSInputStreamのインスタンスを作成および初期化できます.次の例は、ファイルからNSInputStreamを作成する例です.
- (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];
}
の例では、オブジェクトを作成した後にdelegateを設定する必要があります.とみなす
NSInputStreamオブジェクトはrun loopに構成され、ストリームに関連するイベント(たとえばストリームに読み取り可能なデータがある)が発生すると、オブジェクトが受信します.
stream:handleEvent:メッセージ.
Open streamの前に、ストリームオブジェクトにscheduleInRunLoop:forMode:メッセージを送信して、run loopがstream eventsを受信するように構成します.これにより、ストリームにデータ読み取り可能なデータがない場合、delegateブロックを回避することができる.ストリームが別のスレッドで発生している場合は、ストリームオブジェクトがそのスレッドのrun loopに構成されていることを確認する必要があります.ストリームオブジェクトを含むrun loopを除くスレッドから対流操作を試みるべきではありません.最後に、NSInputStreamオブジェクトに対してopenメッセージを送信し、入力データのストリーム操作を開始する.
二、Stream Eventsの処理
ストリームオブジェクトにopenメッセージを送信すると、現在のステータスを検索できます.次のメッセージを使用して、ストリーム・オブジェクトにデータが読み取り可能かどうか、およびエラーのプロパティがあるかどうかを確認します.streamStatus hasBytesAvailable streamError
返されるステータスは
NSStreamStatus定数は、ストリームオブジェクトがopening、reading、またはat the end of the streamなどであることを示すことができます.返されるエラーは、発生する可能性のあるすべてのエラー情報をカプセル化したNSErrorオブジェクトです.
重要なのは、openストリームオブジェクトが、そのdelegateにstream:handleEvent:を送信し続けるということです. メッセージはストリームオブジェクトの最後に達するまで表示されます.これらのメッセージのパラメータには、ストリームイベントのタイプを示すNSStreamEvent定数が含まれています.NSInputStreamオブジェクトで最も一般的なイベントタイプは、NSStreamEventOpenCompleted、NSStreamEventHasBytesAvailable、NSStreamEventEndEncounteredです.私たちが特に興味を持っているのは、NSStreamEventHasBytesAvailableイベントです.次の例は、NSStreamEventHasBytesAvailableイベントを処理する良い方法です.
- (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
}

stream:handleEvent:関数switch文を使用してNSStreamEvent定数を判別します.この定数がMSStreamEventHasBytesAvailableの場合、delegate関数はNSMutableDataオブジェクトをlazy createします.dataは、読み出したデータを受信する.1024のサイズのuint 8_を宣言しますt型配列buf、readを呼び出す:maxLength:関数streamから指定したサイズのデータをbufに読み込み、読み込みに成功するとdelegateは読み込んだデータをNSMutableDataオブジェクトに追加する_Dataでは、合計の読み出しデータbytesReadを更新する.
一度にstreamからどれだけのデータを読み出すかについては、一般的に、512 Bytes、1 kB、4 kB(ページサイズ)などの一般的なデータサイズ仕様が使用されます.
三、stream objectの処理
NSInputStreamオブジェクトがsteamの最後に達すると、stream:handleEvent:関数にNSStream EventEndEncounteredイベントタイプ定数が送信されます.delegate関数は、ストリームオブジェクトを使用する準備とは逆の操作を行う必要があります.つまり、run loopから削除し、最終的にストリームオブジェクトを解放する必要があります.次のコードに示します.
- (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 ...
    }
}