ошибка повреждения базы данных при копировании базы данных monodroid - PullRequest
0 голосов
/ 17 февраля 2012

Я до сих пор разрабатывал приложение для Android на Eclipse, и теперь я использую Mono for Android.

Я пытаюсь скопировать базу данных из папки «Ресурсы», скопировать ее на SD-карту и затем прочитать данные с нее. Я использую следующий код для того же. Однако я получаю ошибка повреждения базы данных .

После запуска следующего кода на SD-карте создается пустая база данных, но сама таблица не копируется.

Также как проверить содержимое SD-карты в MonoDevelop . В настоящее время я использую затмение для того же.

Поскольку я только начинаю разработку Android, любая помощь приветствуется.

public class DbManager
{
    private Context ctx;
    private SQLiteDatabase mDb;
    private DatabaseHelper dataHelper;
    private String DATABASE_PATH = "/data/data/HelloM4A.HelloM4A/databases/";
    private static String DATABASE_NAME = "CompanyMaster.db";
    private SQLiteCursor cur;
    private String[] b1;
    private int x;
    private static int DATABASE_VERSION = 1;

    public DbManager(Context ctx)
    {
        this.ctx = ctx;
        dataHelper = new DatabaseHelper(ctx);
    }

    private class DatabaseHelper : Android.Database.Sqlite.SQLiteOpenHelper
    {
        public DatabaseHelper AnyName
        { get; set; }
        Context myContext = null;

        public DatabaseHelper(Context context)
            : base(context, DATABASE_NAME, null, DATABASE_VERSION)
        {
            this.myContext = context;
        }

        public override void OnCreate(Android.Database.Sqlite.SQLiteDatabase db)
        {
        }

        public override void OnUpgrade(Android.Database.Sqlite.SQLiteDatabase db, 
                                       int oldVersion, int newVersion)
        {
            OnCreate(db);
        }
    }

    public bool checkDataBase()
    {
        String myPath = DATABASE_PATH + DATABASE_NAME;
        Java.IO.File f = new Java.IO.File(myPath);
        return f.Exists();
    }

    public void createDataBase()
    {
        openDB();
        try
        {
            Stream stream;
            string destPath = Path.Combine(Environment.GetFolderPath(
            Environment.SpecialFolder.Personal), "CompanyMaster.db");

            if (new Java.IO.File(destPath).Exists())
                using (stream = ctx.Assets.Open("CompanyMaster.db"))
                {
                    OutputStream myOutput = new FileOutputStream(DATABASE_PATH +
                                                                 DATABASE_NAME);

                    byte[] buffer = new byte[1024];
                    int length;
                    while ((length = stream.Read(buffer, 0, 1024)) > 0)
                    {
                        myOutput.Write(buffer, 0, length);
                    }

                    if (mDb.IsOpen == true)
                        mDb.Close();
                    myOutput.Flush();
                    myOutput.Close();
                    stream.Close();
                }
        }
        catch (Exception e)
        { }
    }

    public DbManager openDB()
    {
        try
        {
            mDb = dataHelper.WritableDatabase;
        }
        catch (Exception e)
        { }
        return this;
    }

    public String[] getSymbol()
    {
        try
        {
            cur = (SQLiteCursor)mDb.RawQuery("select symbol, company_name " + 
                                             "from Scrip", null);
        }
        catch (SQLiteException e)
        { }
        b1 = new String[2168];
        x = 0;
        if (cur.MoveToFirst())
        {
            do`
            {
                b1[x] = cur.GetString(cur.GetColumnIndex("symbol"));
                x++;
            }
            while (cur.MoveToNext());
        }
        cur.Close();
        return b1;
    }

    public void close()
    {
        mDb.Close();
    }
}

EDIT

После различных предложений я попробовал следующий код:

public void createDataBase()
{
    openDB();

    try    
    {           
        var dataFile = ctx.ApplicationContext
                          .GetDatabasePath(DATABASE_NAME)
                          .AbsolutePath;
        Console.WriteLine("path="+
                          ctx.ApplicationContext
                             .GetDatabasePath(DATABASE_NAME)
                             .AbsolutePath);

        // I get path=/data/data/HelloM4A.HelloM4A/databases/CompanyMaster.db 
        // which is correct.
        if (!System.IO.File.Exists(dataFile))
        {
            using (var input = ctx.Assets.Open(DATABASE_NAME))
            using (var output = System.IO.File.Create(dataFile))
            {
                var buffer = new byte[1024];
                int len;
                while ((len = input.Read(buffer, 0, buffer.Length)) > 0)
                {
                    output.Write(buffer, 0, len);
                }
            }
        }
    }
    catch
    {

    }  
}

public DbManager openDB()
{
    try
    {
        mDb = dataHelper.WritableDatabase;
    }
    catch
    {

    }

    return this;
}

Теперь проблема в том, что если я не использую openDB() в пределах createDataBase(), это дает fileNotFoundException.

и если я использую openDB() в createDataBase(), он создаст пустую БД, и, следовательно, БД не будет скопирована, и я получу пустую БД в качестве окончательного вывода из-за следующего условия if (!System.IO.File.Exists(dataFile)).

Поскольку уже создана пустая БД, она не перемещается внутрь, если.

Что тут можно сделать?

1 Ответ

1 голос
/ 17 февраля 2012

Я использую этот код для копирования из папки ресурсов туда, куда я хочу (вы должны иметь возможность изменить его в соответствии с вашими потребностями):

const string dbName = "evolution.sqlite";
var dataDirectory = Path.Combine(ApplicationContext.FilesDir.AbsolutePath,
                                 "databases");
var dataFile = Path.Combine(dataDirectory, dbName);

if (!Directory.Exists(dataDirectory))
{
    Directory.CreateDirectory(dataDirectory);
}

if (!File.Exists(dataFile))
{
    using (var input = ApplicationContext.Assets.Open(dbName))
    using (var output = File.Create(dataFile))
    {
        var buffer = new byte[1024];
        int len;
        while ((len = input.Read(buffer, 0, buffer.Length)) > 0)
        {
            output.Write(buffer, 0, len);
        }
    }
}

Примечание: я динамически создаю путь, так как использую ORM вместо вспомогательных классов БД. Вы можете использовать dataDirectory = context.GetDatabasePath("").AbsolutePath(); вместо.

Вы должны сделать это, прежде чем использовать DatabaseHelper, так как база данных также попытается создать базу данных. Я делаю это в моем Activity.OnCreate(...) методе, а затем использую DatabaseHelper.

Таким образом, если мой код был в функции с именем CopyDB (...), вы используете метод:

public DbManager openDB()
{
    CopyDB(...);

    try
    {
        mDb = dataHelper.WritableDatabase;
    }
    catch(Exception e) 
    {
    }

    return this;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...