IOS 读二进制数据文件
IOS 讀二進制數據文件
在開發項目的過程中,我們有可能遇到上面這圖片展示的數據。其實這些數據是存放到文件中的二進制數據。記得大學的時候老師帶著我們寫了一個記賬類軟件,當時就是把賬單里面的數據存放到文件里面。我直接簡述那時候是怎么做的。首先得有個賬單類。
------------------賬單類的頭文件-----------------
//
//? Payout.h
//? NoteTaking
//
//? Created by?劉超?on 12-12-3.
//? Copyright (c) 2012年劉超. All rights reserved.
//
#import?<Foundation/Foundation.h>
#define KAmountKey? ? @"Amount"
#define KTimekey? ? ? @"Time"
#define KTypeKey? ? ? @"Type"
#define KCommentKey ? @"Comment"
@interface?Payout :?NSObject<NSCoding,NSCopying>
@property?(assign,nonatomic)float?amount;
@property?(strong,nonatomic)NSDate?* time;
@property?(strong,nonatomic)NSString?* type;
@property?(strong,nonatomic)NSString?* comment;
-(NSString*)setMoth:(NSDate*)datetime;
-(NSString*)getType;
@end
------------------賬單類的原文件-----------------
//
//? Payout.m
//? NoteTaking
//
//? Created by?劉超?on 12-12-3.
//? Copyright (c) 2012年劉超. All rights reserved.
//
#import?"Payout.h"
@implementation?Payout
@synthesize?amount;
@synthesize?time;
@synthesize?type;
@synthesize?comment;
-(void)encodeWithCoder:(NSCoder?*)encoder
{
? ? [encoder?encodeFloat:amountforKey:KAmountKey];
? ? [encoder?encodeObject:timeforKey:KTimekey];
? ? [encoder?encodeObject:typeforKey:KTypeKey];
? ? [encoder?encodeObject:commentforKey:KCommentKey];
}
-(id)initWithCoder:(NSCoder?*)decoder
{
? ??if?(self=[superinit]) {
? ? ? ??amount=[decoderdecodeFloatForKey:KAmountKey];
? ? ? ??time=[decoderdecodeObjectForKey:KTimekey];
? ? ? ??type=[decoderdecodeObjectForKey:KTypeKey];
? ? ? ??comment=[decoderdecodeObjectForKey:KCommentKey];
? ? }
? ??returnself;
}
-(id)copyWithZone:(NSZone?*)zone
{
? ??Payout*copy=[[[selfclass]allocWithZone:zone]init];
? ? copy.amount=amount;
? ? copy.time=[self.timecopyWithZone:zone];
? ? copy.type=[self.typecopyWithZone:zone];
? ? copy.comment=[self.commentcopyWithZone:zone];
? ??return?copy;
}
-(NSString*)setMoth:(NSDate*)datetime
{
? ??//datetime= self.time;
? ??NSDateFormatter*atime=[[NSDateFormatteralloc]init];
? ? [atime?setDateStyle:NSDateFormatterMediumStyle];
? ? [atime?setTimeStyle:NSDateFormatterShortStyle];
? ? [atime?setDateFormat:@"MM"];
? ??NSString*moth=[atimestringFromDate:self.time];
???return?moth;
}
@end??
這個類的每一個成員變量都遵循了<NSCoping>協議。為什么要實現此協議呢?因為我們數據寫到文件中,其事就是一個拷貝的過程,需要進行。我們要拷貝一份數據,拷貝后的兩份數據互相不影響,是一份獨立的克隆體,修改一份中的數據時另一份中的數據不會相互影響。這就需要實現<NSCopying>協議: -( id )copyWithZone:( NSZone ?*)zone方法或<NSMutableCopying>協議的:- (id)mutableCopyWithZone:(NSZone?*)zone。接下來就是要把數據寫在文件中,存放到該應用程序沙盒里面。首先得有個路徑來存放數據,獲取路徑的方法如下。
#define KFilenme? ? @"aehive"
-(NSString*)dataFilepath
{
? ??NSArray*paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
? ??NSString*documentDirectory=[pathsobjectAtIndex:0];
? ??return?[documentDirectorystringByAppendingPathComponent:KFilenme];
}
接著我們就是要有兩個最重要的方法來進行文件的讀寫操作。我就直接上代碼了。
-(void) writeList:(NSMutableArray?*) list To:(NSString?*) fileName//寫的函數
{
? ??NSMutableData*data=[[NSMutableDataalloc]init];//聲明一個可變數據類型
? ??NSKeyedArchiver*archiver=[[NSKeyedArchiveralloc]initForWritingWithMutableData:data];//編碼
? ? [archiver?encodeObject:listforKey:KDataKey];//存放數據文件的類型和名字
? ? [archiver?finishEncoding];//編碼完成
? ? [data?writeToFile:[selfdataFilepath]atomically:YES];//寫在相應的路徑下
}
-(NSMutableArray?*) readListFromFile:(NSString?*) fileName//讀的函數
{
? ??if?([[NSFileManagerdefaultManager]fileExistsAtPath:fileName])//是否存在要讀的數據類型,如果存在
? ? {
? ? ? ??NSData*data=[[NSMutableDataalloc]initWithContentsOfFile:fileName];//打開名為fileName數據類型的數據
?? ? ??NSKeyedUnarchiver*unarchiver=[[NSKeyedUnarchiveralloc]initForReadingWithData:data];//解碼
? ? ? ??NSMutableArray?* array = [unarchiverdecodeObjectForKey:KDataKey];//把解碼出來的數據存放在可變數組里面
? ? ? ? [unarchiver?finishDecoding];//解碼完成
? ? ? ??if?(!array) {
? ? ? ? ? ? array=[[NSMutableArrayalloc]init];
? ? ? ? }
? ? ? ??return?array;//返回該數組
? ? }
?? ?
? ??return?[[NSMutableArrayalloc]init];;//如果不存在名為fileName數據類型直接返回空
}
可以看出這種把數據寫到文件中,其實就是利用NSKeyedArchiver歸檔(將各種類型的對象存到文件中) ,編碼后直接調用- (BOOL)writeToFile:(NSString?*)path atomically:(BOOL)useAuxiliaryFile;寫到文件中就可以了。讀出來的時候也是調用相應的函數讀出來,然后解碼。這個存進去的數據就可以完全讀出來了。寫到這里,可能大家會認為關于文件的讀寫就完了。其實今天的重點還沒有開始。
我們在iOS中NSKeyedArchiver方法來歸檔數據。數據的讀寫相對容易得多了。有時候我們拿到的文件是其它平臺把一個已經定義好了的結構體等數據以二進制的方式存放到文件中。問題就來了這時候怎么讀數據呢?其實這時候我們就要用到下面的方法來對數據進行讀的操作。這些數據存儲空間里面是有相應的長度的,我們知道了該結構體的定義,就可以知道該結構體的長度,然后就可以把這些數據一個字節一個字節的拷貝出來。這需要我們iOS端有與之相應的結構體。下面這段代碼就是對一份文件中存了很多個相同結構的結構數據拷貝出來。大概思想就是我們做了一個循環來讀每一個結構體的數據,只要拷貝的總字節小于文件的總字節數。就說明這個數據還沒有讀到末尾。還用了一個變量來紀錄目前讀過的總字節數。具體代碼如下。
NSString?*path = [[NSBundlemain Bundle]pathForResource:@"n9gps"ofType:@"rbb"];
//獲取數據
NSData?*reader = [NSDatadata WithContentsOfFile:path];
//得到文件的長度(大小)
NSInteger?nSize = [reader?length];
NSInteger?nPos =0;
NSMutableDictionary*dataDic=[[NSMutableDictionaryalloc]init];
char* pBuffer = [readerbytes];
while?(nPos<nSize) {
structRMBDM_FRAMEHEADER?frameHeader={0};
memcpy(&frameHeader, pBuffer+nPos,sizeof(RMBDM_FRAMEHEADER));
nPos +=?sizeof(RMBDM_FRAMEHEADER);
structRMBDM_DATETIME?dataTime={0};
structRMBDM_GPS?dataGps={0};
memcpy(&dataTime, pBuffer+nPos,sizeof(RMBDM_DATETIME));
nPos +=?sizeof(RMBDM_DATETIME);
memcpy(&dataGps, pBuffer+nPos,sizeof(RMBDM_GPS));
nPos +=?sizeof(RMBDM_GPS);
NSString*time=[NSStringstringWithFormat:@"%d-%d-%d %d:%d:%d",dataTime.stuDateTime.cYear,dataTime.stuDateTime.cMonth,dataTime.stuDateTime.cDay,dataTime.stuDateTime.cHour,dataTime.stuDateTime.cMinute,dataTime.stuDateTime.cSecond];
N9MRmdbGpsInfo* rmdbGpsInfo=[[N9MRmdbGpsInfoalloc]init];
rmdbGpsInfo.cVersion=[NSStringstringWithFormat:@"%d",dataGps.cVersion];
rmdbGpsInfo.cGpsSource=[NSStringstringWithFormat:@"%d",dataGps.cGpsSource];
rmdbGpsInfo.reserved1=[NSStringstringWithFormat:@"%d",dataGps.reserved1];
rmdbGpsInfo.cGpsStatus=[NSStringstringWithFormat:@"%d",dataGps.cGpsStatus];
rmdbGpsInfo.cSpeedUnit=[NSStringstringWithFormat:@"%d",dataGps.cSpeedUnit];
rmdbGpsInfo.usSpeed=dataGps.usSpeed;
rmdbGpsInfo.cDirectionLatitude=[NSStringstringWithFormat:@"%d",dataGps.cDirectionLatitude];
rmdbGpsInfo.cDirectionLongitude=[NSStringstringWithFormat:@"%d",dataGps.cDirectionLongitude];
rmdbGpsInfo.cLongitudeCent=[NSStringstringWithFormat:@"%d",dataGps.cLongitudeCent];
rmdbGpsInfo.lLatitudeSec=dataGps.lLatitudeSec;
rmdbGpsInfo.lLongitudeSec=dataGps.lLongitudeSec;
rmdbGpsInfo.usGpsAngle=dataGps.usGpsAngle;
rmdbGpsInfo.cGpPlanetNum=[NSStringstringWithFormat:@"%d",dataGps.cGpPlanetNum];
rmdbGpsInfo.cBdPlanetNum=[NSStringstringWithFormat:@"%d",dataGps.cBdPlanetNum];
rmdbGpsInfo.cSignalStrength=[NSStringstringWithFormat:@"%d",dataGps.cSignalStrength];
[dataDic?setObject:rmdbGpsInfoforKey:time];
}
總結
以上是生活随笔為你收集整理的IOS 读二进制数据文件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 杰洛特的Python之旅01_抓取微信性
- 下一篇: VMware收购云监控公司Wavefro