【iOS開發(fā)】python解析sqlite數(shù)據(jù)庫

1. 引言

在iOS開發(fā)調(diào)試過程中,打印日志是最常使用的手段,但是打印日志有時候無法提供詳細(xì)的信息用于問題的分析,?例如一般的消息數(shù)據(jù)由于數(shù)據(jù)量較大,打印日志時只會選擇將一些關(guān)鍵信息打印出來,信息不夠完整。因此,如果能將存入sqlite數(shù)據(jù)庫中的數(shù)據(jù)導(dǎo)出,對于問題的分析定位解決?將會十分有幫助。

2. python解析sqlite基本數(shù)據(jù)類型[1]

2.1 數(shù)據(jù)庫基本操作

  • 數(shù)據(jù)庫連接
import sqlite3
conn = sqlite3.connect('example.db')  
  • 數(shù)據(jù)庫連接對象基本操作
cur = conn.cursor()    //創(chuàng)建cursor
conn.commit()          //事務(wù)提交
conn.rollback()        //事務(wù)回滾
conn.close()           //關(guān)閉一個數(shù)據(jù)庫鏈接
  • 數(shù)據(jù)庫cursor基本操作
cur.execute()    //執(zhí)行sql語句
cur.fetchone()   //從結(jié)果中取出一條記錄
cur.fetchall()   //從結(jié)果中取出所有記錄
cur.close()      //關(guān)閉cursor

2.2 獲取數(shù)據(jù)庫中的表

sqlite數(shù)據(jù)庫中都包含一個特殊的表sqlite_master,其表結(jié)構(gòu)為:

CREATE TABLE sqlite_master (
type TEXT,
name TEXT,
tbl_name TEXT,
rootpage INTEGER,
sql TEXT);

可以利用此表來查詢數(shù)據(jù)庫中所有的表:

tables = cur.execute("select name from sqlite_master where type = 'table' order by name").fetchall()

2.3 獲取表結(jié)構(gòu)

columns = cur.execute("PRAGMA table_info(%s)" % table).fetchall()

2.4 獲取表中的數(shù)據(jù)

data = cur.execute("select * from %s" % table).fetchall()

3. iOS序列化存儲

在iOS開發(fā)中,經(jīng)常將可能會擴(kuò)展或者根據(jù)不同類型存儲不同數(shù)據(jù)的數(shù)據(jù)庫字段定義為blob類型,采用NSKeyedArchiver對具有差異性的數(shù)據(jù)進(jìn)行序列化,轉(zhuǎn)為NSData數(shù)據(jù)進(jìn)行存儲。

例如消息的數(shù)據(jù)表結(jié)構(gòu)可定義為:

CREATE TABLE ?message (
msgId integer primary key,
msgType int,
extensionData blob);

其中extensionData就可以根據(jù)消息的類型(?例如文本、圖片、多媒體等),存儲不同的數(shù)據(jù);同時extensionData中的數(shù)據(jù)還可以在不改變表結(jié)構(gòu)的條件下,進(jìn)行其自身的數(shù)據(jù)擴(kuò)展。

?假設(shè)圖片消息類定義為:

@interface PicMsg : NSObject
@property (nonatomic, assign) NSUInteger msgType;
@property (nonatomic, strong) PicInfo *picInfo;
@end

其中PicInfo為圖片基本信息:

@interface PicInfo : NSObject<NSCoding>
@property (nonatomic, assign) ?NSUInteger picType;
@property (nonatomic, assign) ?NSUInteger fileSize;
@property (nonatomic, assign) ?NSUInteger picWidth;
@property (nonatomic, assign) ?NSUInteger picHeight;
@end
@implementation PicInfo
-(void)encodeWithCoder:(NSCoder *)coder
{
    [coder encodeObject:@(self.picType) forKey:@"picType"];
    [coder encodeObject:@(self.fileSize) forKey:@"fileSize"];
    [coder encodeObject:@(self.picWidth) forKey:@"picWidth"];
    [coder encodeObject:@(self.picHeight) forKey:@"picHeight"];
}
-(id)initWithCoder:(NSCoder *)decoder
{
    if (self = [super init]) {
        self.msgType = [[decoder decodeObjectForKey:@"picType"] unsignedIntegerValue];
        self.fileSize = [[decoder decodeObjectForKey:@"fileSize"] unsignedIntegerValue];
        self.picWidth = [[decoder decodeObjectForKey:@"picWidth"] unsignedIntegerValue];
        self.picHeight = [[decoder decodeObjectForKey:@"picHeight"] unsignedIntegerValue];
    }
    return self;
}
@end

這樣在存入數(shù)據(jù)庫時就可以調(diào)用[NSKeyedArchiver archivedDataWithRootObject:self.picFileInfo];,將picInfo轉(zhuǎn)化為NSData存入extensionData字段里。

4. python+pyobjc[2]解析序列化數(shù)據(jù)

4.1 pyobjc

PyObjC is a bridge between Python and Objective-C. It allows full featured Cocoa applications to be written in pure Python. It is also easy to use other frameworks containing Objective-C class libraries from Python and to mix in Objective-C, C and C++ source.

在使用pyobjc和iOS相關(guān)框架時,只需要import相關(guān)模塊即可,例如Foundation框架:

from Foundation import *

4.2 pyobjc解析序列化數(shù)據(jù)

  • 定義?對應(yīng)類

要對打包數(shù)據(jù)進(jìn)行解包,需要用python定義與OC相對應(yīng)的類。
例如第3節(jié)中提到的PicInfo,改用python定義為:

class PicInfo(NSObject):
    def init(self):
        self = super(PicInfo, self).init()
        if self is None:
            print "init None"
        return self
    def initWithCoder_(self, encoder):
        self = super(PicInfo, self).init()
        if self is None:
            print "initWithCoder_ None"
        self.picType = encoder.decodeObjectForKey_("picType")
        self.fileSize = encoder.decodeObjectForKey_("fileSize")
        self.picWidth = encoder.decodeObjectForKey_("picWidth")
        self.picHeight = encoder.decodeObjectForKey_("picHeight")
        return self
    def encodeWithCoder_(self, decoder):
        decoder.encodeObject_forKey_(self.picType, "picType")
        decoder.encodeObject_forKey_(self.fileSize, "fileSize")
        decoder.encodeObject_forKey_(self.picWidth, "picWidth")
        decoder.encodeObject_forKey_(self.picHeight, "picHeight")
  • 數(shù)據(jù)的序列化與反序列化
picInfo = PicInfo.alloc().init()
picInfo.picType = 1
picInfo.fileSize = 1024
picInfo.picWidth = 200
picInfo.picHeight = 100
// 序列化
archivedData = NSKeyedArchiver.archivedDataWithRootObject_(picInfo)
// 反序列化
unarchivedPicInfo = NSKeyedUnarchiver.unarchiveObjectWithData_(archivedData)

5. 結(jié)語

python+pyobjc不僅僅可以在iOS開發(fā)時進(jìn)行數(shù)據(jù)的序列化和反序列化,利用pyobjc可以在Mac OS上使用純python開發(fā)Cocoa GUI應(yīng)用,功能非常強(qiáng)大。

參考資料

[1]sqlite3 DB-API 2.0 interface for SQLite databases
[2]pyobjc module
[3]pyobjc package documentation

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容