Запись большого количества данных из веб-службы в файл кусками - PullRequest
1 голос
/ 17 января 2012

Я пытаюсь решить общую ситуацию получения большого объема данных от веб-сервисов через:

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

Для небольших данных я просто использую:

[webData appendData:data];

и в конце:

-(void)connectionDidFinishLoading:(NSURLConnection *)connection

Я записываю его в свой файл, используя поток вывода.

Как насчет того, когда данные огромны, пара МБ данных? В этом случае было бы лучше сбросить данные из connection:didReceiveData: несколько раз в один и тот же файл. Звучит просто, используя NSFileHandle, но синхронизация для чтения и записи с учетом асинхронного / неблокирующего интерфейса не является простой (по крайней мере, для меня).

Есть идеи, что было бы хорошим подходом для этого случая? Я думал использовать NSThread, каждый раз помещая в очередь размер куска. Есть ли лучший / легкий подход для этого?

Ответы [ 2 ]

2 голосов
/ 17 января 2012

Вы знаете, я действительно сделал класс для этого некоторое время назад (не ARC, но он все еще должен работать), доступным здесь

Пример использования:

// in init
RJRStreamWriter myWriter = [[RJRStreamWriter alloc] initWithLocalFile:@"path/to/my/file" andAppend:NO];

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    static dispatch_queue_t asyncQueue;
    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{
           asyncQueue = dispatch_queue_create("asyncQueue", NULL);
    });

    dispatch_async(asyncQueue, ^{
        // this method is optimized, and aggregates NSOutputStream, NSMutableData, and NSFileHandle
        [myWriter writeData:data];
    });
}
1 голос
/ 17 января 2012

Для начала пара мегабайт невелика. Делать это одинаково для пары МБ было бы абсолютно нормально. Но если вы хотите записать файл при получении данных, вы можете использовать NSFileHandle. Создайте его, а затем запишите в него данные, а затем вызовите synchronizeFile, когда хотите сбросить данные на диск. Вы можете позвонить synchronizeFile после того, как написано, что каждые 10 МБ записаны или что-то еще (и, очевидно, в конце).

Так, например .:

NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:filename];
...
[fileHandle writeData:dataComeInFromURLConnection];
...
[fileHandle synchronizeFile];
...