新しいアプリで使用したい SQLite に完全に入力されたデータベースがあります。かなり大きいので、できれば別の形式に変更するのは避けたいです。このデータベースをアプリに同梱する方法で使用するにはどうすればよいですか?
編集: たとえば、ファイルをサポートされているファイルのディレクトリにドロップした場合、どのようにアクセスできますか? どのように参照すればよいですか?
新しいアプリで使用したい SQLite に完全に入力されたデータベースがあります。かなり大きいので、できれば別の形式に変更するのは避けたいです。このデータベースをアプリに同梱する方法で使用するにはどうすればよいですか?
編集: たとえば、ファイルをサポートされているファイルのディレクトリにドロップした場合、どのようにアクセスできますか? どのように参照すればよいですか?
を使用すると、SQLite データベースとのやり取りをシンプルかつクリーンにすることができますFMDB Framework
。FMDB は、SQLite C インターフェイスの Objective-C ラッパーです。
読む価値のある参照:
SQLite DB
アプリケーションのバンドルに他のファイルと同様に追加し、次のコードを使用してデータベースをドキュメント ディレクトリにコピーし、ドキュメント ディレクトリからデータベースを使用します。
src/fmdb
ます (src/sample
またはsrc/extra
フォルダーではありません)。にコピーexisting database
して、アプリケーション全体app's document
でdidFinishLaunchingWithOptions:
データベース パスを維持します。
AppDelegate に次のコードを追加します。
AppDelegate.m
#import "AppDelegate.h"
@implementation AppDelegate
// Application Start
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Function called to create a copy of the database if needed.
[self createCopyOfDatabaseIfNeeded];
return YES;
}
#pragma mark - Defined Functions
// Function to Create a writable copy of the bundled default database in the application Documents directory.
- (void)createCopyOfDatabaseIfNeeded {
// First, test for existence.
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
// Database filename can have extension db/sqlite.
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *appDBPath = [documentsDirectory stringByAppendingPathComponent:@"database-name.sqlite"];
success = [fileManager fileExistsAtPath:appDBPath];
if (success) {
return;
}
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"database-name.sqlite"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:appDBPath error:&error];
NSAssert(success, @"Failed to create writable database file with message '%@'.", [error localizedDescription]);
}
YourViewController.m
#import "FMDatabase.h"
- (void)getAllData {
// Getting the database path.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsPath = [paths objectAtIndex:0];
NSString *dbPath = [docsPath stringByAppendingPathComponent:@"database-name.sqlite"];
FMDatabase *database = [FMDatabase databaseWithPath:dbPath];
[database open];
NSString *sqlSelectQuery = @"SELECT * FROM tablename";
// Query result
FMResultSet *resultsWithNameLocation = [database executeQuery:sqlSelectQuery];
while([resultsWithNameLocation next]) {
NSString *strID = [NSString stringWithFormat:@"%d",[resultsWithNameLocation intForColumn:@"ID"]];
NSString *strName = [NSString stringWithFormat:@"%@",[resultsWithNameLocation stringForColumn:@"Name"]];
NSString *strLoc = [NSString stringWithFormat:@"%@",[resultsWithNameLocation stringForColumn:@"Location"]];
// loading your data into the array, dictionaries.
NSLog(@"ID = %d, Name = %@, Location = %@",strID, strName, strLoc);
}
[database close];
}
#import "FMDatabase.h"
- (void)insertData {
// Getting the database path.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsPath = [paths objectAtIndex:0];
NSString *dbPath = [docsPath stringByAppendingPathComponent:@"database-name.sqlite"];
FMDatabase *database = [FMDatabase databaseWithPath:dbPath];
[database open];
NSString *insertQuery = [NSString stringWithFormat:@"INSERT INTO user VALUES ('%@', %d)", @"Jobin Kurian", 25];
[database executeUpdate:insertQuery];
[database close];
}
- (void)updateDate {
// Getting the database path.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsPath = [paths objectAtIndex:0];
NSString *dbPath = [docsPath stringByAppendingPathComponent:@"fmdb-sample.sqlite"];
FMDatabase *database = [FMDatabase databaseWithPath:dbPath];
[database open];
NSString *insertQuery = [NSString stringWithFormat:@"UPDATE users SET age = '%@' WHERE username = '%@'", @"23", @"colin" ];
[database executeUpdate:insertQuery];
[database close];
}
#import "FMDatabase.h"
- (void)deleteData {
// Getting the database path.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsPath = [paths objectAtIndex:0];
NSString *dbPath = [docsPath stringByAppendingPathComponent:@"database-name.sqlite"];
FMDatabase *database = [FMDatabase databaseWithPath:dbPath];
[database open];
NSString *deleteQuery = @"DELETE FROM user WHERE age = 25";
[database executeUpdate:deleteQuery];
[database close];
}
行数の取得
FMDatabaseAdditions.h
使用するファイルを必ず含めてくださいintForQuery:
。
#import "FMDatabase.h"
#import "FMDatabaseAdditions.h"
- (void)gettingRowCount {
// Getting the database path.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsPath = [paths objectAtIndex:0];
NSString *dbPath = [docsPath stringByAppendingPathComponent:@"database-name.sqlite"];
FMDatabase *database = [FMDatabase databaseWithPath:dbPath];
[database open];
NSUInteger count = [database intForQuery:@"SELECT COUNT(field_name) FROM table_name"];
[database close];
}
アプリケーション バンドル内の他のファイルと同様に、Sqlite DB を追加します。
コードを介してドキュメントディレクトリにコピーして使用します。これの目的は、ドキュメントディレクトリでのみsqliteのコンテンツを更新できるようにすることです
-(void) checkAndCreateDatabase
{
// Check if the SQL database has already been saved to the users phone, if not then copy it over
BOOL success;
// Create a FileManager object, we will use this to check the status
// of the database and to copy it over if required
NSFileManager *fileManager = [NSFileManager defaultManager];
// Check if the database has already been created in the users filesystem
success = [fileManager fileExistsAtPath:_databasePath];
// If the database already exists then return without doing anything
if(success) return;
// If not then proceed to copy the database from the application to the users filesystem
// Get the path to the database in the application package
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:_databaseName];
// Copy the database from the package to the users filesystem
[fileManager copyItemAtPath:databasePathFromApp toPath:_databasePath error:nil];
}
- (id)init {
if ((self = [super init]))
{
_databaseName = DB_NAME;
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
_databasePath = [documentsDir stringByAppendingPathComponent:_databaseName];
if (sqlite3_open([[self dbPath] UTF8String], &_database) != SQLITE_OK)
{
[[[UIAlertView alloc]initWithTitle:@"Missing"
message:@"Database file not found"
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil, nil]show];
}
}
return self;
}
Swift、シングルトン クラス、および FMDB を使用します。以下のコードを使用して、非常に簡単に実現できます。
import Foundation
class LocalDatabase: NSObject {
//sharedInstance
static let sharedInstance = LocalDatabase()
func methodToCreateDatabase() -> NSURL? {
let fileManager = NSFileManager.defaultManager()
let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
if let documentDirectory:NSURL = urls.first { // No use of as? NSURL because let urls returns array of NSURL
// exclude cloud backup
do {
try documentDirectory.setResourceValue(true, forKey: NSURLIsExcludedFromBackupKey)
} catch _{
print("Failed to exclude backup")
}
// This is where the database should be in the documents directory
let finalDatabaseURL = documentDirectory.URLByAppendingPathComponent("contact.db")
if finalDatabaseURL.checkResourceIsReachableAndReturnError(nil) {
// The file already exists, so just return the URL
return finalDatabaseURL
} else {
// Copy the initial file from the application bundle to the documents directory
if let bundleURL = NSBundle.mainBundle().URLForResource("contact", withExtension: "db") {
do {
try fileManager.copyItemAtURL(bundleURL, toURL: finalDatabaseURL)
} catch _ {
print("Couldn't copy file to final location!")
}
} else {
print("Couldn't find initial database in the bundle!")
}
}
} else {
print("Couldn't get documents directory!")
}
return nil
}
func methodToInsertUpdateDeleteData(strQuery : String) -> Bool
{
// print("%@",String(methodToCreateDatabase()!.absoluteString))
let contactDB = FMDatabase(path: String(methodToCreateDatabase()!.absoluteString) )
if contactDB.open() {
let insertSQL = strQuery
let result = contactDB.executeUpdate(insertSQL,
withArgumentsInArray: nil)
if !result {
print("Failed to add contact")
print("Error: \(contactDB.lastErrorMessage())")
return false
} else {
print("Contact Added")
return true
}
} else {
print("Error: \(contactDB.lastErrorMessage())")
return false
}
}
func methodToSelectData(strQuery : String) -> NSMutableArray
{
let arryToReturn : NSMutableArray = []
print("%@",String(methodToCreateDatabase()!.absoluteString))
let contactDB = FMDatabase(path: String(methodToCreateDatabase()!.absoluteString) )
if contactDB.open() {
let querySQL = strQuery
let results:FMResultSet? = contactDB.executeQuery(querySQL,
withArgumentsInArray: nil)
while results?.next() == true
{
arryToReturn.addObject(results!.resultDictionary())
}
// NSLog("%@", arryToReturn)
if arryToReturn.count == 0
{
print("Record Not Found")
}
else
{
print("Record Found")
}
contactDB.close()
} else {
print("Error: \(contactDB.lastErrorMessage())")
}
return arryToReturn
}
}
ディレクトリに .sqlite ファイルをコピーするには...
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
// Database filename can have extension db/sqlite.
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *databasePath = [documentsDirectory stringByAppendingPathComponent:@"MapView.sqlite"];
success = [fileManager fileExistsAtPath:databasePath];
// if (success){
// return;
// }
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"MapView.sqlite"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:databasePath error:&error];
if (!success) {
//NSAssert1(0, @"Failed to create writable database file with message '%@'.", [error localizedDescription]);
}
else
{
NSLog(@"Database created successfully");
}
データベースからデータを選択するには...
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &mapDB) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat: @"SELECT * FROM maplatlong"];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(mapDB, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
while(sqlite3_step(statement) == SQLITE_ROW)
{
NSString *cityN = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
NSString *lat = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)];
NSString *longi = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 2)];
[cityName addObject:cityN];
[latitude addObject:lat];
[longitude addObject:longi];
}
sqlite3_finalize(statement);
}
sqlite3_close(mapDB);
}