NSFileHandle
方法 | 描述 |
---|---|
+(NSFileHandle *)fileHandleForReadingAtPath:path | 打开文件以便读取 |
+(NSFileHandle *)fileHandleForWritingAtPath:path | 打开文件以便写入 |
+(NSFileHandle *)fileHandleForUpdatingAtPath:path | 打开文件以便读写 |
-(NSData *)availableData | 返回文件有效字符长度(bytes),有个问题是,如果在超大文件中用该方法,内存会暴涨直到卡死,该方法会将文件读入内存,然后计算长度,此时文件句柄指向文件结尾。 |
-(NSData *)readDataToEndOfFile | 读取文件末尾处之前的数据 |
-(NSData *)readDataOfLength:(NSUInteger)bytes | 读取指定长度的字节.这里也有个问题:当你存储汉字的时候,如果读取的字节数正好把一个汉字分多次读取,NSData中是有数据的.但是不能用NSString打印出来,此时打印出来为null. |
-(void)writeData:data | 将数据data写入文件 |
-(unsigned long long)offsetInFile | 获取当前文件中的操作位置 |
-(void)seekToFileOffset:offset | 将当前文件的操作位置设定为offset |
-(unsigned long long)seekToEndOfFile | 返回整个文件大小,并将读写指针移到文件尾部.该方法和上面的一个方法都是在磁盘上操作的,并没有将文件读到内存 |
-(void)truncateFileAtOffset:offset | 将文件的长度设定为offset |
-(void)closeFile | 关闭文件 |
读取文件
//读取对应路径下的文件大小
+ (unsigned long long)getSizeWithFilePath:(nonnull NSString *)filePath error:(NSError **)error
{
NSFileManager *fm = [NSFileManager defaultManager];
NSDictionary *attributes = [fm attributesOfItemAtPath:filePath error:error];
return attributes.fileSize;
}
或
/**
NSFileHandle *fileHande = [NSFileHandle fileHandleForReadingAtPath:filePath];
return [fileHande seekToEndOfFile];
*/
//读取对应路径下的文件
+ (NSData *)fileData:(NSString *)filePath {
/**
NSError *readError;
NSFileHandle *fileHande = [NSFileHandle fileHandleForReadingFromURL:[NSURL URLWithString:filePath] error:&readError];
if (!readError) {
NSData *readData = [fileHande readDataToEndOfFile];
[fileHande closeFile];
return readData;
}
//也闪退
NSFileHandle *fileHande = [NSFileHandle fileHandleForReadingAtPath:filePath];
return [fileHande readDataToEndOfFile];
*/
NSFileHandle *fileHande = [NSFileHandle fileHandleForReadingAtPath:filePath];
return [fileHande availableData];
}
注意:以上读取文件的方式只适用于小文件读取,小于5M或者再大点,如果是大文件的读取,app内存会暴涨,绝壁会闪退。具体原因见 iOS读取文件闪退
操作文件
文件分片
uint64_t offset = uplodFile.totalBytes / chuckCount;//每个分片大小 = 总大小 / 分片数量
for (int i = 1; i <= chuckCount; i++) {
//打开文件
NSFileHandle* readHandle = [NSFileHandle fileHandleForReadingAtPath:filePath];
//seek文件
[readHandle seekToFileOffset:offset * (i -1)];
//读取每个分片中的文件
NSData* data = [readHandle readDataOfLength:offset];
}
获取文件类型后缀
[NSString stringWithFormat:@".%@",[filePath pathExtension]];
获取文件的MINIType
- (NSString *)getMIMETypeWithCAPIAtFilePath:(NSString *)path
{
if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
return nil;
}
CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)[path pathExtension], NULL);
CFStringRef MIMEType = UTTypeCopyPreferredTagWithClass (UTI, kUTTagClassMIMEType);
CFRelease(UTI);
if (!MIMEType) {
return @"application/octet-stream";//任意的二进制文件
}
return (__bridge NSString *)(MIMEType);
}
获取文件大小
+ (unsigned long long)getSizeWithFilePath:(nonnull NSString *)filePath error:(NSError **)error
{
/**
NSFileHandle *fileHande = [NSFileHandle fileHandleForReadingAtPath:filePath];
return [fileHande seekToEndOfFile];
*/
NSFileManager *fm = [NSFileManager defaultManager];
NSDictionary *attributes = [fm attributesOfItemAtPath:filePath error:error];
return attributes.fileSize;
}
//计算文件的大小,单位为 M,这种计算大文件绝壁闪退
- (CGFloat)fileSize:(NSURL *)url {
return [[NSData dataWithContentsOfURL:url] length] / 1024.00 / 1024.00;
}
文件另存和删除
int32_t const VH_CHUNK_SIZE = 8 * 1024;
//另存为
- (NSString *)writefile:(NSString *)filePath
{
//写入文件路径
NSString *toPath = [NSString stringWithFormat:@"%@/%@",NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject,[filePath lastPathComponent]];
//如果存在,先删除
if ([[NSFileManager defaultManager] fileExistsAtPath:toPath]) {
[[NSFileManager defaultManager] removeItemAtPath:toPath error:nil];
}
//创建文件路径
if (![[NSFileManager defaultManager] createFileAtPath:toPath contents:nil attributes:nil]) {
return nil;
}
//打开文件
NSFileHandle *sourceHandle = [NSFileHandle fileHandleForReadingAtPath:filePath];
NSFileHandle *writeHandle = [NSFileHandle fileHandleForWritingAtPath:toPath];
if(sourceHandle == nil || writeHandle == nil) {
return nil;
}
//读取文件写入
BOOL done = NO;
while(!done) {
@autoreleasepool{
NSData *data = [sourceHandle readDataOfLength:VH_CHUNK_SIZE];
if([data length] == 0) {
done = YES;
}
[writeHandle seekToEndOfFile];
[writeHandle writeData:data];
data = nil;
}
}
//关闭文件
[sourceHandle closeFile];
[writeHandle closeFile];
return toPath;
}
//删除本地上传的文件
- (BOOL)deletefile:(NSString *)uploadPath {
if ([[NSFileManager defaultManager] fileExistsAtPath:uploadPath]) {
BOOL removed = [[NSFileManager defaultManager] removeItemAtPath:uploadPath error:nil];
OSSLogDebug(@"removed file %@ %@",uploadPath,removed?@"sucess":@"failed");
return removed;
}
return NO;
}
未完待续…