Ответ 1
Вы можете использовать NSData +dataWithContentsOfFile:options:error:
с опцией NSDataReadingMappedIfSafe
, чтобы скопировать файл в память, а не загружать его. Таким образом, он будет использовать диспетчер виртуальной памяти в iOS, чтобы гарантировать, что биты файла будут заменены и выведены из ОЗУ таким же образом, что операционная система Windows обрабатывает свой файл виртуальной памяти на диске. Таким образом, вам не нужно достаточно оперативной памяти для одновременного хранения всего файла в памяти, вам просто нужно, чтобы файл был достаточно мал, чтобы вписываться в адресное пространство процессора (так, гигабайты). Вы получите объект, который будет действовать как обычный NSData
, который должен сэкономить вам большую часть проблем, связанных с использованием NSFileHandle
и ручным потоком.
Вам, вероятно, понадобится преобразовать части в NSString
, так как вы можете реально ожидать, что конвертировать из UTF-8 в другой формат (хотя это может и не быть: стоит пойти с -initWithData:encoding:
и посмотреть, будет ли NSString достаточно умен, чтобы поддерживать ссылку на исходные данные и расширяться с UTF-8 по требованию), который, по моему мнению, является тем, на что ваш вопрос действительно попадает.
Я бы предложил использовать -initWithBytes:length:encoding:
для преобразования разумного количества байтов в строку. Затем вы можете использовать -lengthOfBytesUsingEncoding:
, чтобы узнать, сколько байтов оно действительно имело смысл и соответствующим образом улучшить ваш указатель чтения. Это безопасное предположение, что NSString
будет отбрасывать любые части символов в конце предоставленных вами байтов.
EDIT: так что-то вроде:
// map the file, rather than loading it
NSData *data = [NSData dataWithContentsOfFile:...whatever...
options:NSDataReadingMappedIfSafe
error:&youdDoSomethingSafeHere];
// we'll maintain a read pointer to our current location in the data
NSUinteger readPointer = 0;
// continue while data remains
while(readPointer < [data length])
{
// work out how many bytes are remaining
NSUInteger distanceToEndOfData = [data length] - readPointer;
// grab at most 16kb of them, being careful not to read too many
NSString *newPortion =
[[NSString alloc] initWithBytes:(uint8_t *)[data bytes] + readPointer
length:distanceToEndOfData > 16384 ? 16384 : distanceToEndOfData
encoding:NSUTF8StringEncoding];
// do whatever we want with the string
[self doSomethingWithFragment:newPortion];
// advance our read pointer by the number of bytes actually read, and
// clean up
readPointer += [newPortion lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
[newPortion release];
}
Конечно, подразумеваемое предположение состоит в том, что все кодировки UTF-8 уникальны, и я должен признать, что он недостаточно осведомлен, чтобы сказать для абсолютного определенного.