当前位置: 首页 > 知识库问答 >
问题:

如何将数据库从内部存储复制到外部存储(假设为下载文件夹)?

贺飞
2023-03-14

在我的应用程序中,有一个由sqlite创建的数据库。我想将数据库复制到下载文件夹。我使用的是不同的方式,但并没有在真实的设备上工作(它说拒绝访问目录),可能是它想要根手机。请帮助,我想提供一个访问权限,以便用户可以从下载文件夹获取数据库。

请注意,我使用的是最新版本的android studio。

在下面给定的DatabaseHelper类中。在exportDB()方法中,我要实现这一点。

package com.tarikul.sqlitedatabase1;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Environment;
import android.widget.Toast;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;

public class DatabaseHelper extends SQLiteOpenHelper {
    private static final String DATABASE_NAME = "Students.db";
    private static final String TABLE_NAME = "student_details";
    private static final String ID = "_id";
    private static final String NAME = "Name";
    private static final String AGE = "Age";
    private static final String GENDER = "Gender";
    private static final int  VERSION_NUMBER = 1;
    private static final String CREATE_TABLE = "CREATE TABLE "+TABLE_NAME+"("+ID+" INTEGER PRIMARY KEY AUTOINCREMENT, "+NAME+" VARCHAR(155), "+AGE+" INTEGER, "+GENDER+" VARCHAR(15));";
    private static final String DROP_TABLE = "DROP TABLE IF EXISTS " + TABLE_NAME;
    private static final String SELECT_ALL_DATA = "SELECT * FROM " + TABLE_NAME;

    private Context context;

    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, VERSION_NUMBER);
        this.context=context;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        try {
            db.execSQL(CREATE_TABLE);
            Toast.makeText(context,"OnCreate is called.",Toast.LENGTH_SHORT).show();
        }catch (Exception e){
            Toast.makeText(context,"Exception: "+e,Toast.LENGTH_SHORT).show();
        }


    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        try {
            Toast.makeText(context,"onUpgrade is called.",Toast.LENGTH_SHORT).show();
            db.execSQL(DROP_TABLE);
            onCreate(db);

        }catch (Exception e){
            Toast.makeText(context,"Exception: "+e,Toast.LENGTH_SHORT).show();
        }

    }

    public long insert(String name, String age, String gender)
    {
        SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
        ContentValues contentValues = new ContentValues();
        contentValues.put(NAME,name);
        contentValues.put(AGE,age);
        contentValues.put(GENDER,gender);
        long rowId = sqLiteDatabase.insert(TABLE_NAME,null,contentValues);
        return rowId;
    }

    public Cursor displayAllData(){
        SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
        Cursor cursor = sqLiteDatabase.rawQuery(SELECT_ALL_DATA,null);
        return cursor;
    }

    public boolean updateData(String id, String name, String age, String gender)
    {
        SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
        ContentValues contentValues = new ContentValues();
        contentValues.put(ID,id);
        contentValues.put(NAME,name);
        contentValues.put(AGE,age);
        contentValues.put(GENDER,gender);

        sqLiteDatabase.update(TABLE_NAME, contentValues,ID + " = ?",new String[]{id});
        return true;
    }

    public int deleteData(String id)
    {
        SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
        return sqLiteDatabase.delete(TABLE_NAME,ID + " = ?", new String[]{id});
    }

    public void exportDB()
    {

    }

}

共有1个答案

卞琨
2023-03-14

简言之,你需要

>

  • 在清单中有:-

    如果构建版本为23或更高,请在运行时检查/请求它,例如,我使用:-

    if(Build.VERSION.SDK_INT >= 23) {
        ExternalStoragePermissions.verifyStoragePermissions(this);
    }
    

    以及:-

    class ExternalStoragePermissions {
    
        public int API_VERSION = Build.VERSION.SDK_INT;
        private static final int REQUEST_EXTERNAL_STORAGE = 1;
        private static String[] PERMISSIONS_STORAGE = {
    
                Manifest.permission.WRITE_EXTERNAL_STORAGE
        };
    
        public ExternalStoragePermissions() {}
        // Note call this method
        public static void verifyStoragePermissions(Activity activity) {
    
            int permission = ActivityCompat.checkSelfPermission(
                    activity,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE);
    
            if(permission != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(
                        activity,
                        PERMISSIONS_STORAGE,
                        REQUEST_EXTERNAL_STORAGE
                );
            }
        }
    }
    
    • 注:上述操作应在应用程序首次启动时完成

    如果数据库使用预写日志记录(WAL),则应关闭数据库或至少检查数据库。在WAL模式下,事务(更新/插入/删除)存储在-WAL和-shm文件中。只有在提交这些事务(关闭或完全检查点)时,数据库的一部分才会保存在这些文件中,因此您需要这些数据。

    在日志模式下,对数据库所做的更改存储在-journal文件中。这些可用于回滚在数据库中所做的更改(在WAL中回滚是从-WAL和-shm文件中删除更改,因此它们永远不会应用于数据库文件)。

    如果需要,添加到DatabaseHelper类的以下方法将检查数据库:-

    private void checkpointIfWALEnabled(Context context, String databaseName) {
        Cursor csr;
        int wal_busy = -99, wal_log = -99, wal_checkpointed = -99;
        SQLiteDatabase db = SQLiteDatabase.openDatabase(context.getDatabasePath(databaseName).getPath(), null, SQLiteDatabase.OPEN_READWRITE);
        csr = db.rawQuery("PRAGMA journal_mode", null);
        if (csr.moveToFirst()) {
            String mode = csr.getString(0);
            if (mode.toLowerCase().equals("wal")) {
                csr = db.rawQuery("PRAGMA wal_checkpoint", null);
                if (csr.moveToFirst()) {
                    wal_busy = csr.getInt(0);
                    wal_log = csr.getInt(1);
                    wal_checkpointed = csr.getInt(2);
                }
                csr = db.rawQuery("PRAGMA wal_checkpoint(TRUNCATE)", null);
                csr.getCount();
                csr = db.rawQuery("PRAGMA wal_checkpoint", null);
                if (csr.moveToFirst()) {
                    wal_busy = csr.getInt(0);
                    wal_log = csr.getInt(1);
                    wal_checkpointed = csr.getInt(2);
                }
            }
        }
        csr.close();
        db.close();
    }
    

    例如。下面是您可以使用的核心代码示例

            public void exportDB() {
    
                this.getWritableDatabase().close();
                try {
                    String dbfilename = this.getDatabasePath(DATABASE_NAME).getPath();
                    File dbfile = new File(dbfilename);
                    String backupfilename = (new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),null)).getPath() + File.separator + DATABASE_NAME + "-backup";
                    checkpointIfWALEnabled(context,DATABASE_NAME);
                    FileInputStream fis = new FileInputStream(dbfile);
                    OutputStream backup = new FileOutputStream(backupfilename);
                    String methodname = new Object() {
                    }.getClass().getEnclosingMethod().getName();
    
                    byte[] buffer = new byte[32768]; //32k buffer, may be changed
                    int length;
                    while ((length = fis.read(buffer)) > 0) {
                        backup.write(buffer, 0, length);
                    }
                    backup.flush();
                    backup.close();
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    
    • 注意:上面的代码是从更复杂的代码中提取出来的,并且经过了轻微的调整。它尚未测试或运行,因此可能存在一些小错误

  •  类似资料:
    • 我试图使用Adobe reader读取从服务器下载的pdf文件,但问题是当我将其存储在内部存储时,其他应用程序无法读取该文件。现在我想知道如何将此文件复制到外部存储(/sdcard/)中,以便pdf查看器可以查看。 由于安全原因,我将文件存储在内部存储,然后删除外部存储的文件。 我的问题是如何复制保存在内部存储中的文件,而不使用raw或将其放入InputStream中的资产。

    • 问题内容: 我的应用程序( Android API 15 )制作图片并将其存储在内部存储器的文件夹中。现在,我想将此文件复制到外部存储中的另一个文件夹,例如。我尝试了以下方法: 方法1: 方法2: 方法3: 这些方法都不能解决我的任务。在检查了许多相关主题之后,我发现的唯一建议是验证 在和它确实存在。 该 方法#1 完成执行,但没有文件夹和文件被复制。 在 方法#2 ,应用程序失败,异常的,但对象

    • 这些方法都不能解决我的任务。中检查了一些相关主题,我发现的唯一建议是验证 在中,并且它仍然存在。 方法#1完成执行,但没有复制文件夹和文件。 因为这是我迈向Android的第一步,我觉得我错过了一些小东西。请告诉我,如何在Android中将文件从一个文件夹复制到另一个文件夹,包括文件从内部内存移动到外部内存。

    • 问题内容: 如何复制到外部存储保持,以便以后可以共享首选项。 试图读取并另存为一个文件,创建了类型,但我需要一个。想过遍历应用程序的内部存储和复制文件,然后将其放入外部存储,但这可能太复杂了。 真的很想知道是否存在一种简单而明智的方式来传递`sharedpreferences。 问题答案: 使用此代码, 并取回它, 注意 使用此代码只能处理字符串类型首选项,

    • 我写了一个Android应用。导出为签名APK发送通过邮件安装到设备。-不在市场。 在运行时,它将用类似的代码将他们的数据保存到内部存储: 据我所知-如果我错了,请纠正我-它将保存到/data/data/com。我的公司。myapp/文件名 因为它是用保存的,所以我不确定市场上或我的其他应用程序是否能看到它保存它。也许如果我创建一个具有相同签名的应用程序? 手机没有根。我已经尝试了很多备份,应用程

    • 那是外部存储代码,但我想保存在Android手机的内部存储。