views:

445

answers:

3

I am reading a very large file using a NSInputStreamer and sending them to a device in packets. If the receiver does not get a packet, I can send back to the sender with a packet number, representing the starting location in bytes of the packet missing.

I know an NSInputStreamer cannot rewind and grab the packet, but is there another way to grab the requested byte range without loading the entire large file into memory?

If there was a [NSData dataWithContentsOfFileAtPath:inRange] method, it would be perfect.

A: 

I believe "Stream programming guide" at apple developer site has an answer on page 12.

Eimantas
This wont get a particular offset in the file at any given time. I am using something similar to this to get the data for the stream in general, but what I need is a way to get back to a specific range in case something went wrong.
coneybeare
+3  A: 

I don't think there's a standard function that does that, but you could write one yourself, using a category and the C stdio API:

@interface NSData(DataWithContentsOfFileAtOffsetWithSize)
+ (NSData *) dataWithContentsOfFile:(NSString *)path atOffset:(off_t)offset withSize:(size_t)bytes;
@end

@implementation NSData(DataWithContentsOfFileAtOffsetWithSize)

+ (NSData *) dataWithContentsOfFile:(NSString *)path atOffset:(off_t)offset withSize:(size_t)bytes
{
  FILE *file = fopen([path UTF8String], "rb");
  if(file == NULL)
        return nil;

  void *data = malloc(bytes);  // check for NULL!
  fseeko(file, offset, SEEK_SET);
  fread(data, 1, bytes, file);  // check return value, in case read was short!
  fclose(file);

  // NSData takes ownership and will call free(data) when it's released
  return [NSData dataWithBytesNoCopy:data length:bytes];
}

@end

Then you can this:

// Read 100 bytes of data beginning at offset 500 from "somefile"
NSData *data = [NSData dataWithContentsOfFile:@"somefile" atOffset:500 withSize:100];
Adam Rosenfield
+1  A: 

You can rewind with NSInputStream:

[stream setProperty:[NSNumber numberWithInt:offset]
             forKey:NSStreamFileCurrentOffsetKey];
Chris Suter