文章来源:淘论文网   发布者: 毕业设计   浏览量: 33



还可以点击去查询以下关键词:
[使用]    [LevelDB]    [在OC中使用LevelDB]   

项目介绍:

在OC中使用LevelDB

主题 《iOS开发》 by evan

一.LevelDB简介

为什么有了FMDB这么强大,方便的数据库,还要去用LevelDB呢?原因是当你的app需要处理的数据上万条时,FMDB显得很吃力,这个吃力表现在效率上,数据库的操作,肯定都有加锁,上万条数据排队去执行,加上反序列化的一些操作,没有个几十秒是搞不定的。所以,我们需要一个更高效的数据库。

1.简介

首先,LevelDb是一个持久化存储的KV系统,和Redis这种内存型的KV系统不同,LevelDb不会像Redis一样狂吃内存,开题报告,而是将大部分数据存储到磁盘上。

其次,LevleDb在存储数据时,是根据记录的key值有序存储的,就是说相邻的key值在存储文件中是依次顺序存储的,而应用可以自定义key大小比较函数,LevleDb会按照会员定义的比较函数依序存储这些记录。

再次,像大多数KV系统一样,LevelDb的操作接口很简单,基本操作包括写记录,读记录以及删除记录。也支持针对多条操作的原子批量操作。

另外,LevelDb支持数据快照(snapshot)功能,使得读取操作不受写操作影响,可以在读操作过程中始终看到一致的数据。

除此外,LevelDb还支持数据压缩等操作,这对于减小存储空间以及增快IO效率都有直接的帮助。

LevelDb性能非常突出,开题报告,官方网站报道其随机写性能达到40万条记录每秒,而随机读性能达到6万条记录每秒。总体来说,LevelDb的写操作要大大快于读操作,而顺序读写操作则大大快于随机读写操作。至于为何是这样,看了朗格科技后续推出的LevelDb日知录,估计您会了解其内在原因。

2.有关LevelDB的更多详细介绍文档

LevelDB Cache源码精读——缓存

LevelDB Random源码精读——随机数

LevelDb日知录

二.LevelDB编译成静态库

LevelDB的项目托管在google/leveldb

其实很早以前就已经有人为LevelDB写了Objective-C的接口,今天抽时间写一个类似NSUserDefaults的接口,以后我就可以在自己的项目中用它来替代SQLite了。

如果需要使用LevelDB,首先需要去Clone托管在google code上的代码,然后将代码编译成静态库:

如果需要编译成Mac OSX系统的静态库:

cd leveldb CSSFLAGS=-stdlib=libc++ make

如果需要编译成iOS系统的静态库:

cd leveldb CSSFLAGS=-stdlib=libc++ make PLATFORM=IOS

然后讲inlude头和libleveldb.a拖到自己的工程中,到此就可以使用LevelDB提供的接口了,由于LevelDB是用C++开发的,所以在使用的时候记得将.m修改为.mm

三.LevelDB编译成framework

如果你想把LevelDB编译成framework使用,那么你需要创建一个FrameWork工程

然后引入inlude头和libleveldb.a,这时候编译会报错

把"leveldb/"删掉就好了。

四.用OC去封装LevelDB

不管你是直接引用LevelDB的静态库还是编译成framework,都是需要去用OC的代码封装一层,然后才可以调用。

// // CSPLevelDB.h // CSPLevelDB // // Created by evan on 15/4/20. // Copyright (c) 2015年 evan. All rights reserved. // #import <UIKit/UIKit.h> //! Project version number for CSPLevelDB. FOUNDATION_EXPORT double CSPLevelDBVersionNumber; //! Project version string for CSPLevelDB. FOUNDATION_EXPORT const unsigned char CSPLevelDBVersionString[]; // In this header, you should import all the public headers of your framework using statements like #import <CSPLevelDB/PublicHeader.h> #import <Foundation/Foundation.h> extern NSString * const CSPLevelDBErrorDomain; @class CSPLevelDBIterator; @protocol CSPLevelDBWriteBatch; @interface CSPLevelDB : NSObject @property (nonatomic, readonly, strong) NSString *path; + (CSPLevelDB *)levelDBWithPath:(NSString *)path error:(NSError **)errorOut; - (void)close; - (BOOL)setData:(NSData *)data forKey:(NSString *)key; - (BOOL)setString:(NSString *)str forKey:(NSString *)key; - (BOOL)setArray:(NSArray *)data forKey:(NSString *)key; - (BOOL)setDictionary:(NSDictionary *)data forKey:(NSString *)key; - (BOOL)setBool:(BOOL)val forKey:(NSString *)key; - (BOOL)setInt:(int)val forKey:(NSString *)key; - (BOOL)setLong:(long long)val forKey:(NSString *)key; - (BOOL)setFloat:(float)val forKey:(NSString *)key; - (BOOL)setDouble:(double)val forKey:(NSString *)key; - (BOOL)setNumber:(NSNumber *)val forKey:(NSString *)key; - (NSData *)dataForKey:(NSString *)key; - (NSArray *)arrayForKey:(NSString *)key; - (NSDictionary *)dictionaryForKey:(NSString *)key; - (NSString *)stringForKey:(NSString *)key; - (BOOL)boolForKey:(NSString *)key; - (int)intForKey:(NSString *)key; - (long long)longForKey:(NSString *)key; - (float)floatForKey:(NSString *)key; - (double)doubleForKey:(NSString *)key; - (BOOL)removeKey:(NSString *)key; - (NSArray *)allKeys; - (void)enumerateKeys:(void (^)(NSString *key, BOOL *stop))block; - (void)enumerateKeysAndValuesAsStrings:(void (^)(NSString *key, NSString *value, BOOL *stop))block; // Objective-C Subscripting Support: // The database object supports subscripting for string-string and string-data key-value access and assignment. // Examples: // db[@'key'] = @'value'; // db[@'key'] = [NSData data]; // NSString *s = db[@'key']; // An NSInvalidArgumentException is raised if the key is not an NSString, or if the assigned object is not an // instance of NSString or NSData. - (id)objectForKeyedSubscript:(id)key; - (void)setObject:(id)object forKeyedSubscript:(id<NSCopying>)key; // Batch write/atomic update support: - (id<CSPLevelDBWriteBatch>)beginWriteBatch; - (BOOL)commitWriteBatch:(id<CSPLevelDBWriteBatch>)batch; @end @interface CSPLevelDBIterator : NSObject + (id)iteratorWithLevelDB:(CSPLevelDB *)db; // Designated initializer: - (id)initWithLevelDB:(CSPLevelDB *)db; - (BOOL)seekToKey:(NSString *)key; - (NSString *)nextKey; - (NSString *)key; - (NSString *)valueAsString; - (NSData *)valueAsData; @end @protocol CSPLevelDBWriteBatch <NSObject> - (void)setData:(NSData *)data forKey:(NSString *)key; - (void)setString:(NSString *)str forKey:(NSString *)key; - (void)setArray:(NSArray *)data forKey:(NSString *)key; - (void)setDictionary:(NSDictionary *)data forKey:(NSString *)key; - (void)setBool:(BOOL)val forKey:(NSString *)key; - (void)setInt:(int)val forKey:(NSString *)key; - (void)setLong:(long long)val forKey:(NSString *)key; - (void)setFloat:(float)val forKey:(NSString *)key; - (void)setDouble:(double)val forKey:(NSString *)key; - (void)setNumber:(NSNumber *)val forKey:(NSString *)key; - (void)removeKey:(NSString *)key; // Remove all of the buffered sets and removes: - (void)clear; @end #p#分页标题#e#

.mm文件实现

// // CSPLevelDB.h // CSPLevelDB // // Created by evan on 15/4/20. // Copyright (c) 2015年 evan. All rights reserved. // #import 'CSPLevelDB.h' #import 'db.h' #import 'options.h' #import 'write_batch.h' #import <vector> NSString * const CSPLevelDBErrorDomain = @'CSPLevelDBErrorDomain'; #define SliceFromString(_string_) (leveldb::Slice((char *)[_string_ UTF8String], [_string_ lengthOfBytesUsingEncoding:NSUTF8StringEncoding])) #define StringFromSlice(_slice_) ([[NSString alloc] initWithBytes:_slice_.data() length:_slice_.size() encoding:NSUTF8StringEncoding]) @interface CSPLevelDBWriteBatch : NSObject <CSPLevelDBWriteBatch> { @package leveldb::WriteBatch _batch; } @end #pragma mark - CSPLevelDB @interface CSPLevelDB () { leveldb::DB *_db; leveldb::ReadOptions _readOptions; leveldb::WriteOptions _writeOptions; } - (id)initWithPath:(NSString *)path error:(NSError **)errorOut; + (leveldb::Options)defaultCreateOptions; @property (nonatomic, readonly) leveldb::DB *db; @end @implementation CSPLevelDB @synthesize path = _path; @synthesize db = _db; + (CSPLevelDB *)levelDBWithPath:(NSString *)path error:(NSError **)errorOut { return [[CSPLevelDB alloc] initWithPath:path error:errorOut]; } - (id)initWithPath:(NSString *)path error:(NSError **)errorOut { if ((self = [super init])) { _path = [path copy]; leveldb::Options options = [[self class] defaultCreateOptions]; leveldb::Status status = leveldb::DB::Open(options, [_path UTF8String], &_db); if (!status.ok()) { if (errorOut) { NSString *statusString = [[NSString alloc] initWithCString:status.ToString().c_str() encoding:NSUTF8StringEncoding]; *errorOut = [NSError errorWithDomain:CSPLevelDBErrorDomain code:0 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:statusString, NSLocalizedDescriptionKey, nil]]; } return nil; } _writeOptions.sync = false; } return self; } - (void)dealloc { [self close]; } + (leveldb::Options)defaultCreateOptions { leveldb::Options options; options.create_if_missing = true; return options; } - (void)close { if (_db) { delete _db; _db = NULL; } } - (BOOL)setData:(NSData *)data forKey:(NSString *)key { leveldb::Slice keySlice = SliceFromString(key); leveldb::Slice valueSlice = leveldb::Slice((const char *)[data bytes], (size_t)[data length]); leveldb::Status status = _db->Put(_writeOptions, keySlice, valueSlice); return (status.ok() == true); } - (BOOL)setArray:(NSArray *)data forKey:(NSString *)key { return [self setData:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:key]; } - (BOOL)setDictionary:(NSDictionary *)data forKey:(NSString *)key { return [self setData:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:key]; } - (BOOL)setBool:(BOOL)val forKey:(NSString *)key { return [self setNumber:[NSNumber numberWithBool:val] forKey:key]; } - (BOOL)setInt:(int)val forKey:(NSString *)key { return [self setNumber:[NSNumber numberWithInt:val] forKey:key]; } - (BOOL)setLong:(long long)val forKey:(NSString *)key { return [self setNumber:[NSNumber numberWithLongLong:val] forKey:key]; } - (BOOL)setFloat:(float)val forKey:(NSString *)key { return [self setNumber:[NSNumber numberWithFloat:val] forKey:key]; } - (BOOL)setDouble:(double)val forKey:(NSString *)key { return [self setNumber:[NSNumber numberWithDouble:val] forKey:key]; } - (BOOL)setNumber:(NSNumber *)val forKey:(NSString *)key { return [self setString:[val stringValue] forKey:key]; } - (NSArray *)arrayForKey:(NSString *)key { NSData * data = [self dataForKey:key]; if (data) { return (NSArray *)[NSKeyedUnarchiver unarchiveObjectWithData:data]; } return nil; } - (NSDictionary *)dictionaryForKey:(NSString *)key { NSData * data = [self dataForKey:key]; if (data) { return (NSDictionary *)[NSKeyedUnarchiver unarchiveObjectWithData:data]; } return nil; } - (BOOL)boolForKey:(NSString *)key { NSString * val = [self stringForKey:key]; if (val) { return [val boolValue]; } return NO; } - (int)intForKey:(NSString *)key { NSString * val = [self stringForKey:key]; if (val) { return [val intValue]; } return 0; } - (long long)longForKey:(NSString *)key { NSString * val = [self stringForKey:key]; if (val) { return [val longLongValue]; } return 0; } - (float)floatForKey:(NSString *)key { NSString * val = [self stringForKey:key]; if (val) { return [val floatValue]; } return 0; } - (double)doubleForKey:(NSString *)key { NSString * val = [self stringForKey:key]; if (val) { return [val doubleValue]; } return 0; } - (BOOL)setString:(NSString *)str forKey:(NSString *)key { // This could have been based on leveldb::Slice keySlice = SliceFromString(key); leveldb::Slice valueSlice = SliceFromString(str); leveldb::Status status = _db->Put(_writeOptions, keySlice, valueSlice); return (status.ok() == true); } - (NSData *)dataForKey:(NSString *)key { leveldb::Slice keySlice = SliceFromString(key); std::string valueCPPString; leveldb::Status status = _db->Get(_readOptions, keySlice, &valueCPPString); if (!status.ok()) return nil; else return [NSData dataWithBytes:valueCPPString.data() length:valueCPPString.size()]; } - (NSString *)stringForKey:(NSString *)key { leveldb::Slice keySlice = SliceFromString(key); std::string valueCPPString; leveldb::Status status = _db->Get(_readOptions, keySlice, &valueCPPString); // We assume (dangerously?) UTF-8 string encoding: if (!status.ok()) return nil; else return [[NSString alloc] initWithBytes:valueCPPString.data() length:valueCPPString.size() encoding:NSUTF8StringEncoding]; } - (BOOL)removeKey:(NSString *)key { leveldb::Slice keySlice = SliceFromString(key); leveldb::Status status = _db->Delete(_writeOptions, keySlice); return (status.ok() == true); } - (NSArray *)allKeys { NSMutableArray *keys = [NSMutableArray array]; [self enumerateKeys:^(NSString *key, BOOL *stop) { [keys addObject:key]; }]; return keys; } - (void)enumerateKeysAndValuesAsStrings:(void (^)(NSString *key, NSString *value, BOOL *stop))block { BOOL stop = NO; leveldb::Iterator* iter = _db->NewIterator(leveldb::ReadOptions()); for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { leveldb::Slice key = iter->key(), value = iter->value(); NSString *k = StringFromSlice(key); NSString *v = [[NSString alloc] initWithBytes:value.data() length:value.size() encoding:NSUTF8StringEncoding]; block(k, v, &stop); if (stop) break; } delete iter; } - (void)enumerateKeys:(void (^)(NSString *key, BOOL *stop))block { BOOL stop = NO; leveldb::Iterator* iter = _db->NewIterator(leveldb::ReadOptions()); for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { leveldb::Slice key = iter->key(); NSString *k = StringFromSlice(key); block(k, &stop); if (stop) break; } delete iter; } #pragma mark - Subscripting Support - (id)objectForKeyedSubscript:(id)key { if (![key respondsToSelector: @selector(componentsSeparatedByString:)]) { [NSException raise:NSInvalidArgumentException format:@'key must be an NSString']; } return [self stringForKey:key]; } - (void)setObject:(id)thing forKeyedSubscript:(id<NSCopying>)key { id idKey = (id) key; if (![idKey respondsToSelector: @selector(componentsSeparatedByString:)]) { [NSException raise:NSInvalidArgumentException format:@'key must be NSString or NSData']; } if ([thing respondsToSelector:@selector(componentsSeparatedByString:)]) [self setString:thing forKey:(NSString *)key]; else if ([thing respondsToSelector:@selector(subdataWithRange:)]) [self setData:thing forKey:(NSString *)key]; else [NSException raise:NSInvalidArgumentException format:@'object must be NSString or NSData']; } #pragma mark - Atomic Updates - (id<CSPLevelDBWriteBatch>)beginWriteBatch { CSPLevelDBWriteBatch *batch = [[CSPLevelDBWriteBatch alloc] init]; return batch; } - (BOOL)commitWriteBatch:(id<CSPLevelDBWriteBatch>)theBatch { if (!theBatch) return NO; CSPLevelDBWriteBatch *batch = (CSPLevelDBWriteBatch *) theBatch; leveldb::Status status; status = _db->Write(_writeOptions, &batch->_batch); return (status.ok() == true); } @end #pragma mark - CSPLevelDBIterator @interface CSPLevelDBIterator () { leveldb::Iterator *_iter; } @end @implementation CSPLevelDBIterator + (id)iteratorWithLevelDB:(CSPLevelDB *)db { CSPLevelDBIterator *iter = [[[self class] alloc] initWithLevelDB:db]; return iter; } - (id)initWithLevelDB:(CSPLevelDB *)db { if ((self = [super init])) { _iter = db.db->NewIterator(leveldb::ReadOptions()); _iter->SeekToFirst(); if (!_iter->Valid()) return nil; } return self; } - (id)init { [NSException raise:@'BadInitializer' format:@'Use the designated initializer, -initWithLevelDB:, instead.']; return nil; } - (void)dealloc { delete _iter; _iter = NULL; } - (BOOL)seekToKey:(NSString *)key { leveldb::Slice target = SliceFromString(key); _iter->Seek(target); return _iter->Valid() == true; } - (void)seekToFirst { _iter->SeekToFirst(); } - (void)seekToLast { _iter->SeekToLast(); } - (NSString *)nextKey { _iter->Next(); return [self key]; } - (NSString *)key { if (_iter->Valid() == false) return nil; leveldb::Slice value = _iter->key(); return StringFromSlice(value); } - (NSString *)valueAsString { if (_iter->Valid() == false) return nil; leveldb::Slice value = _iter->value(); return StringFromSlice(value); } - (NSData *)valueAsData { if (_iter->Valid() == false) return nil; leveldb::Slice value = _iter->value(); return [NSData dataWithBytes:value.data() length:value.size()]; } @end #pragma mark - CSPLevelDBWriteBatch @implementation CSPLevelDBWriteBatch - (void)setData:(NSData *)data forKey:(NSString *)key { leveldb::Slice keySlice = SliceFromString(key); leveldb::Slice valueSlice = leveldb::Slice((const char *)[data bytes], (size_t)[data length]); _batch.Put(keySlice, valueSlice); } - (void)setString:(NSString *)str forKey:(NSString *)key { leveldb::Slice keySlice = SliceFromString(key); leveldb::Slice valueSlice = SliceFromString(str); _batch.Put(keySlice, valueSlice); } - (void)setArray:(NSArray *)data forKey:(NSString *)key { [self setData:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:key]; } - (void)setDictionary:(NSDictionary *)data forKey:(NSString *)key { return [self setData:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:key]; } - (void)setBool:(BOOL)val forKey:(NSString *)key { return [self setNumber:[NSNumber numberWithBool:val] forKey:key]; } - (void)setInt:(int)val forKey:(NSString *)key { return [self setNumber:[NSNumber numberWithInt:val] forKey:key]; } - (void)setLong:(long long)val forKey:(NSString *)key { return [self setNumber:[NSNumber numberWithLongLong:val] forKey:key]; } - (void)setFloat:(float)val forKey:(NSString *)key { return [self setNumber:[NSNumber numberWithFloat:val] forKey:key]; } - (void)setDouble:(double)val forKey:(NSString *)key { return [self setNumber:[NSNumber numberWithDouble:val] forKey:key]; } - (void)setNumber:(NSNumber *)val forKey:(NSString *)key { return [self setString:[val stringValue] forKey:key]; } - (void)removeKey:(NSString *)key { leveldb::Slice keySlice = SliceFromString(key); _batch.Delete(keySlice); } - (void)clear { _batch.Clear(); } @end 五.使用LevelDB1.创建LevelDB

_levelDB = [CSPLevelDB sharedDatabase].db;

2.获取batch#p#分页标题#e#

id <CSPLevelDBWriteBatch> batch = [_levelDB beginWriteBatch];

3.调用batch的相应方法存储数据@protocol CSPLevelDBWriteBatch <NSObject> - (void)setData:(NSData *)data forKey:(NSString *)key; - (void)setString:(NSString *)str forKey:(NSString *)key; - (void)setArray:(NSArray *)data forKey:(NSString *)key; - (void)setDictionary:(NSDictionary *)data forKey:(NSString *)key; - (void)setBool:(BOOL)val forKey:(NSString *)key; - (void)setInt:(int)val forKey:(NSString *)key; - (void)setLong:(long long)val forKey:(NSString *)key; - (void)setFloat:(float)val forKey:(NSString *)key; - (void)setDouble:(double)val forKey:(NSString *)key; - (void)setNumber:(NSNumber *)val forKey:(NSString *)key; - (void)removeKey:(NSString *)key; // Remove all of the buffered sets and removes: - (void)clear; @end

调用batch是为了批量处理数据,效率能更高。如果不想调用batch,也可以直接调用LevelDB的相应方法去存储。

4.写入LevelDB

[_levelDB commitWriteBatch:batch];

5.从LevelDB读取数据#p#分页标题#e#

调用相应的方法即可:

- (NSData *)dataForKey:(NSString *)key; - (NSArray *)arrayForKey:(NSString *)key; - (NSDictionary *)dictionaryForKey:(NSString *)key; - (NSString *)stringForKey:(NSString *)key; - (BOOL)boolForKey:(NSString *)key; - (int)intForKey:(NSString *)key; - (long long)longForKey:(NSString *)key; - (float)floatForKey:(NSString *)key; - (double)doubleForKey:(NSString *)key;

友情提示:在对LevleDB做操作的时候,一定要对key做判空处理

有关代码,在OSChina上,感兴趣的同学可以去看看

也可以直接下载代码


这里还有:


还可以点击去查询:
[使用]    [LevelDB]    [在OC中使用LevelDB]   

请扫码加微信 微信号:sj52abcd


下载地址: http://www.taolw.com/down/8695.docx
  • 上一篇:日历组件毕业设计 GFCalendar
  • 下一篇:有关UILabel的行定制高设置的探索