0

ARC 自動変換プロジェクトで作業しています。

巨大なテキスト ファイル (14MB) の内容がNSString *_documentDataString.

今、私はこのループを持っています:

- (void)scanParts
{
    NSString *boundary = [boundaryPrefix stringByAppendingString:_header.boundary];

    NSMutableArray *parts = [NSMutableArray array];

    NSInteger currentLocation = [_documentDataString rangeOfString:boundary].location;

    BOOL reachedTheEnd = NO;
    while(!reachedTheEnd)
    {
        NSInteger nextBoundaryLocation = [[_documentDataString substringFromIndex:currentLocation + 1]
                                          rangeOfString:boundary].location;

        if(nextBoundaryLocation == NSNotFound)
        {
            reachedTheEnd = YES;
        }
        else
        {
            nextBoundaryLocation += currentLocation + 1;

            //[parts addObject:[_documentDataString substringWithRange:
              //                NSMakeRange(currentLocation, nextBoundaryLocation - currentLocation)]];

            currentLocation = nextBoundaryLocation;
        }
    }
}

ただし、これらのエラーが発生し始めます。

 malloc: *** mmap(size=6496256) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug

何がうまくいかないのですか?

このループを実行すると、このエラーが発生し始めます。

while(true)
{
    NSInteger nextBoundaryLocation = [[_documentDataString substringFromIndex:currentLocation + 1]
                                          rangeOfString:boundary].location;
}
4

3 に答える 3

5

substringFromIndex:イン_

NSInteger nextBoundaryLocation = [[_documentDataString substringFromIndex:currentLocation + 1]
                                      rangeOfString:boundary].location;

現在の autoreleasepool が破棄されたとき (たとえば、プログラム制御がメイン イベント ループに戻ったとき) にのみ割り当てが解除される (一時的な自動解放された) サブストリングを作成します。

そのコードを次のように置き換えることができます

NSInteger nextBoundaryLocation = [_documentDataString rangeOfString:boundary
             options:0
               range:NSMakeRange(currentLocation + 1, [_documentDataString length] - (currentLocation + 1))].location;

(うまくいけば)一時的な文字列の作成を回避します。nextBoundaryLocationは、文字列の先頭に対して相対的であることに注意してください。

nextBoundaryLocation += currentLocation + 1;

もう必要ありません。

または、完全なループを単純に置き換えることもできます

NSArray *parts = [_documentDataString componentsSeparatedByString:boundary];
于 2013-05-22T13:40:52.743 に答える
0

文字列オブジェクトのメモリ割り当て中にエラーが発生する理由は、(合理的に) 通常のサイズの文字列で通常行うように、ドキュメントが大きすぎて操作できないようです。

あなたの特定のケースでは、おそらくNSInputStreamファイルのデータを一度にではなくバイトごとに読み取ることができる を使用する必要があります。

次の質問Objective-C: Reading a file line by lineを見てください。

簡単に言えば、ドキュメントによると、次のようなことをする必要があります。

まずファイルを開く

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

ストリームに使用可能なバイトがさらにある場合の処理​​を処理するコードを記述します (ファイルの終わりではない場合)。

- (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;
        }
于 2013-05-22T13:45:54.307 に答える
0

NSInputStreamまた、メモリ使用量を減らすこともできます。iOS デバイスの 14MB は多く終了します。

于 2013-05-22T13:50:02.670 に答える