简体   繁体   中英

Read only a portion of a file from disk in objective-c

I am reading a very large file using a NSInputStream 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 NSInputStream 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.

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

You can rewind with NSInputStream:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM