NSFileHandle简析以及实现超大文件的复制

来源:互联网 发布:小视频生成器软件 编辑:程序博客网 时间:2024/05/18 20:52

1.NSFileHandle 主要函数介绍:

@interface NSFileHandle : NSObject <NSSecureCoding>//NSFileHandle默认打开文件时,读写指针在文件开头.    - (NSData *)availableData;//返回文件有效字符长度(bytes),有个问题是,如果在超大文件中用该方法,会导致电脑卡死.该方法会将文件读入内存,然后计算长度,并且此时,文件句柄指向文件结尾.    - (NSData *)readDataToEndOfFile;//读到文件结尾- (NSData *)readDataOfLength:(NSUInteger)length;//读取指定长度的字节.这里也有个问题:当你存储汉字的时候,如果读取的字节数正好把一个汉字分多次读取,NSData中是有数据的.但是不能用NSString打印出来,此时打印出来为null.- (void)writeData:(NSData *)data;//将数据写到文件中去    - (unsigned long long)offsetInFile;//返回当前文件读写指针偏移量,也就是文件读到哪了.- (unsigned long long)seekToEndOfFile;//返回整个文件大小,并将读写指针移到文件尾部.该方法和上面的一个方法都是在磁盘上操作的,并没有将文件读到内存.- (void)seekToFileOffset:(unsigned long long)offset;//设置读写指针偏移量    - (void)truncateFileAtOffset:(unsigned long long)offset;//截断文件,offset为文件剩余字节大小.可以用该方法清空磁盘文件.- (void)synchronizeFile;//文件同步,具体我也没怎么试过.- (void)closeFile;//关闭文件    @end

2.复制超大文件(亲测,可用)

-(void)copyFileFromPath:(NSString *)path1 toPath:(NSString *)path2{    NSFileHandle * fh1 = [NSFileHandle fileHandleForReadingAtPath:path1];//读到内存    [[NSFileManager defaultManager] createFileAtPath:path2 contents:nil attributes:nil];//写之前必须有该文件    NSFileHandle * fh2 = [NSFileHandle fileHandleForWritingAtPath:path2];//写到文件    NSData * _data = nil;    unsigned long long ret = [fh1 seekToEndOfFile];//返回文件大小   if (ret < 1024 * 1024 * 5) {//小于5M的文件一次读写       [fh1 seekToFileOffset:0];        _data = [fh1 readDataToEndOfFile];       [fh2 writeData:_data];    }else{        NSUInteger n = ret / (1024 * 1024 * 5);        if (ret % (1024 * 1024 * 5) != 0) {            n++;        }        NSUInteger offset = 0;        NSUInteger size = 1024 * 1024 * 5;        for (NSUInteger i = 0; i < n - 1; i++) {            //大于5M的文件多次读写            [fh1 seekToFileOffset:offset];            @autoreleasepool {                /*该自动释放池必须要有否则内存一会就爆了                 原因在于readDataOfLength方法返回了一个自动释放的对象,它只能在遇到自动释放池的时候才释放.如果不手动写这个自动释放池,会导致_data指向的对象不能及时释放,最终导致内存爆了.                 */                _data = [fh1 readDataOfLength:size];                [fh2 seekToEndOfFile];                [fh2 writeData:_data];                NSLog(@"%lu/%lu", i + 1, n - 1);            }            offset += size;        }        //最后一次剩余的字节        [fh1 seekToFileOffset:offset];        _data = [fh1 readDataToEndOfFile];        [fh2 seekToEndOfFile];        [fh2 writeData:_data];    }    [fh1 closeFile];    [fh2 closeFile];}
0 0