Новые NSData с диапазоном старых байтов NSData, поддерживающих - PullRequest
2 голосов
/ 08 апреля 2010

У меня есть довольно большой объект NSData (или NSMutableData, если необходимо), из которого я хочу извлечь небольшой кусок и оставить остальные.Поскольку я работаю с большим количеством байтов NSData, я не хочу делать большую копию, а просто усекаю существующие байты.В основном:

  • NSData * источник: <несколько байтов, которые я хочу отбросить> + <большой кусок байтов, которые я хочу сохранить>
  • NSData * место назначения: <большой кусок байтовЯ хочу сохранить>

В NSMutableData есть методы усечения, но они только обрезают его конец, тогда как я хочу усекать начало.Я думаю, что сделать это с помощью методов:

Обратите внимание, что я использовал неправильный (копирование) метод в оригинальной публикации.Я отредактировал и исправил это

- (const void *)bytes

и

- initWithBytesNoCopy:length:freeWhenDone:

Однако я пытаюсь выяснить, как управлять памятью с этим.Я предполагаю, что процесс будет таким (я разместил там, где я не знаю, что делать):

// Get bytes
const unsigned char *bytes = (const unsigned char *)[source bytes];

// Offset the start
bytes += myStart;

// Somehow (m)alloc the memory which will be freed up in the following step
?????

// Release the source, now that I've allocated the bytes
[source release];

// Create a new data, recycling the bytes so they don't have to be copied
NSData destination = [[NSData alloc]
                      initWithBytesNoCopy:bytes
                      length:myLength
                      freeWhenDone:YES];

Спасибо за помощь!

Ответы [ 4 ]

5 голосов
/ 16 июня 2010

Это то, что вы хотите?

NSData *destination = [NSData dataWithBytes:((char *)source.bytes) + myStart
                                     length:myLength];

Я знаю, что вы сказали: "Я не хочу делать большую копию", но это только та же копия, что вы делали с getBytes:length: в вашем примере, так что это может быть вам хорошо.

Также есть replaceBytesInRange:withBytes:length:, который вы можете использовать так:

[source setLength:myStart + myLength];
[source replaceBytesInRange:NSMakeRange(0, myStart)
                  withBytes:NULL
                     length:0];

Но в документе не говорится, как работает этот метод (без характеристик производительности), и source должен быть NSMutableData.

4 голосов
/ 05 августа 2010

в зависимости от контекста, решения могут быть разными. Я предполагаю, что вам нужен метод, который бы возвращал автоматически выпущенный объект NSData с указанным диапазоном:

- (NSData *)getSubData:(NSData *)source withRange:(NSRange)range
{
    UInt8 bytes[range.length];
    [source getBytes:&bytes range:range];
    NSData *result = [[NSData alloc] initWithBytes:bytes length:sizeof(bytes)];
    return [result autorelease];
}

Конечно, вы можете сделать его методом класса и поместить его в некоторый класс "utils" или создать расширение поверх NSData ...

2 голосов
/ 14 марта 2014

Есть также NSData метод -[subdataWithRange:(NSRange)range], который может добиться цели. Я понятия не имею, как выглядит представление (я думаю, что оно делает копию или две, но я не знаю наверняка). Может использоваться как:

NSData *destination = [source subdataWithRange:NSMakeRange(0, lengthIWant)];
2 голосов
/ 29 января 2013

Если вы хотите избежать копирования блоков памяти, вы можете использовать dataWithBytesNoCopy, чтобы сохранить старый буфер с определенным смещением. В этом примере мы «удаляем» первые 2 байта:

source = [NSData dataWithBytesNoCopy:(char*)source.bytes + 2 length:source.length - 2];

Для простоты примера, проверка границы пропущена, пожалуйста, добавьте ее так, как вам удобно. Доступно в iOS 2.0 и более поздних версиях.

...