【问题标题】:Exporting SQLite Database to csv file in android在android中将SQLite数据库导出到csv文件
【发布时间】:2015-09-30 18:24:45
【问题描述】:

我正在尝试将 SQLite 数据作为目录中的 CSV 文件导出到 Android 中的 SD 卡。

所以我在下面尝试了这种方法,显然它只显示打印出来的文本:

数据库的第一个表
日期、项目、金额、货币

在我的 DBHelper.java 中,我定义了如下函数:

public boolean exportDatabase() {
        DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());

        /**First of all we check if the external storage of the device is available for writing.
         * Remember that the external storage is not necessarily the sd card. Very often it is
         * the device storage.
         */
        String state = Environment.getExternalStorageState();
        if (!Environment.MEDIA_MOUNTED.equals(state)) {
            return false;
        }
        else {
            //We use the Download directory for saving our .csv file.
            File exportDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
            if (!exportDir.exists())
            {
                exportDir.mkdirs();
            }

            File file;
            PrintWriter printWriter = null;
            try
            {
                file = new File(exportDir, "MyCSVFile.csv");
                file.createNewFile();
                printWriter = new PrintWriter(new FileWriter(file));

                /**This is our database connector class that reads the data from the database.
                 * The code of this class is omitted for brevity.
                 */
                SQLiteDatabase db = this.getReadableDatabase(); //open the database for reading

                /**Let's read the first table of the database.
                 * getFirstTable() is a method in our DBCOurDatabaseConnector class which retrieves a Cursor
                 * containing all records of the table (all fields).
                 * The code of this class is omitted for brevity.
                 */
                Cursor curCSV = db.rawQuery("select * from contacts", null);
                //Write the name of the table and the name of the columns (comma separated values) in the .csv file.
                printWriter.println("FIRST TABLE OF THE DATABASE");
                printWriter.println("DATE,ITEM,AMOUNT,CURRENCY");
                while(curCSV.moveToNext())
                {
                    Long date = curCSV.getLong(curCSV.getColumnIndex("date"));
                    String title = curCSV.getString(curCSV.getColumnIndex("title"));
                    Float amount = curCSV.getFloat(curCSV.getColumnIndex("amount"));
                    String description = curCSV.getString(curCSV.getColumnIndex("description"));

                    /**Create the line to write in the .csv file.
                     * We need a String where values are comma separated.
                     * The field date (Long) is formatted in a readable text. The amount field
                     * is converted into String.
                     */
                    String record = df.format(new Date(date)) + "," + title + "," + amount + "," + description;
                    printWriter.println(record); //write the record in the .csv file
                }

                curCSV.close();
                db.close();
            }

            catch(Exception exc) {
                //if there are any exceptions, return false
                return false;
            }
            finally {
                if(printWriter != null) printWriter.close();
            }

            //If there are no errors, return true.
            return true;
        }
    }
}

我的专栏是:

 public static final String DATABASE_NAME = "MyDBName.db";
 public static final String CONTACTS_TABLE_NAME = "contacts";
 public static final String CONTACTS_COLUMN_ID = "id";
 public static final String CONTACTS_COLUMN_TITLE = "title";
 public static final String CONTACTS_COLUMN_AMOUNT = "amount";
 public static final String CONTACTS_COLUMN_DESC = "description";

如果您需要更多代码,请告诉我。

【问题讨论】:

  • 你想要什么?你有什么错误吗?
  • //Write the name of the table and the name of the columns (comma separated values) in the .csv file. 然后,如果您添加表名,它就不再是有效的 CSV 文件。有效 CSV 文件中的第一行要么是带有列名的标题行,要么只是第一个数据行。
  • 关于您的问题...表格中似乎没有数据。
  • @CodeProcessor 不,我没有收到任何错误,CSV 文件只是包含标题而不是 sqlite 数据本身
  • 尝试将 PrintWriter AutoFlush 参数设置为 true。 printWriter = new PrintWriter(new FileWriter(file), true);

标签: android sqlite csv


【解决方案1】:

感谢您的建议让我得到这个答案:

private void exportDB() {

        DBHelper dbhelper = new DBHelper(getApplicationContext());
        File exportDir = new File(Environment.getExternalStorageDirectory(), "");
        if (!exportDir.exists())
        {
            exportDir.mkdirs();
        }

        File file = new File(exportDir, "csvname.csv");
        try
        {
            file.createNewFile();
            CSVWriter csvWrite = new CSVWriter(new FileWriter(file));
            SQLiteDatabase db = dbhelper.getReadableDatabase();
            Cursor curCSV = db.rawQuery("SELECT * FROM contacts",null);
            csvWrite.writeNext(curCSV.getColumnNames());
            while(curCSV.moveToNext())
            {
                //Which column you want to exprort
                String arrStr[] ={curCSV.getString(0),curCSV.getString(1), curCSV.getString(2)};
                csvWrite.writeNext(arrStr);
            }
            csvWrite.close();
            curCSV.close();
        }
        catch(Exception sqlEx)
        {
            Log.e("MainActivity", sqlEx.getMessage(), sqlEx);
        }
}

【讨论】:

  • 不太清楚从哪里获得getDatabasePathDBHelperCSVWriter 和此代码的其他部分。
  • getDatabasePath() 方法查找数据库位置的路径,DBHelper 是我的扩展 sqliteOpenHelper 的 sqlite 处理程序类,CSVWriter 是 CSV 函数。代码直接运行,没有太多麻烦。
  • 很遗憾你没有在这里分享这些课程。它们可能对其他人有用。
  • @SteveKamau 如果我想要所有数据怎么办。
【解决方案2】:

如果有人仍然偶然发现这个问题,我将发布我的解决方案,它比公认的解决方案稍微通用。您应该几乎可以通过复制下面的两个类来导出 sqlite 数据库中的所有表。只有需要的其他更改应该与获取应用程序上下文和导入打开的 csv 相关。

有些部分几乎是从其他 stackoverflow 线程复制粘贴的,但我再也找不到了。

Sqlite 导出器:

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import com.opencsv.CSVWriter;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/**
 * Can export an sqlite databse into a csv file.
 *
 * The file has on the top dbVersion and on top of each table data the name of the table
 *
 * Inspired by
 * https://stackoverflow.com/questions/31367270/exporting-sqlite-database-to-csv-file-in-android
 * and some other SO threads as well.
 *
 */
public class SqliteExporter {
    private static final String TAG = SqliteExporter.class.getSimpleName();

    public static final String DB_BACKUP_DB_VERSION_KEY = "dbVersion";
    public static final String DB_BACKUP_TABLE_NAME = "table";

    public static String export(SQLiteDatabase db) throws IOException{
        if( !FileUtils.isExternalStorageWritable() ){
            throw new IOException("Cannot write to external storage");
        }
        File backupDir = FileUtils.createDirIfNotExist(FileUtils.getAppDir() + "/backup");
        String fileName = createBackupFileName();
        File backupFile = new File(backupDir, fileName);
        boolean success = backupFile.createNewFile();
        if(!success){
            throw new IOException("Failed to create the backup file");
        }
        List<String> tables = getTablesOnDataBase(db);
        Log.d(TAG, "Started to fill the backup file in " + backupFile.getAbsolutePath());
        long starTime = System.currentTimeMillis();
        writeCsv(backupFile, db, tables);
        long endTime = System.currentTimeMillis();
        Log.d(TAG, "Creating backup took " + (endTime - starTime) + "ms.");

        return backupFile.getAbsolutePath();
    }

    private static String createBackupFileName(){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HHmm");
        return "db_backup_" + sdf.format(new Date()) + ".csv";
    }

    /**
     * Get all the table names we have in db
     *
     * @param db
     * @return
     */
    public static List<String> getTablesOnDataBase(SQLiteDatabase db){
        Cursor c = null;
        List<String> tables = new ArrayList<>();
        try{
            c = db.rawQuery("SELECT name FROM sqlite_master WHERE type='table'", null);
            if (c.moveToFirst()) {
                while ( !c.isAfterLast() ) {
                    tables.add(c.getString(0));
                    c.moveToNext();
                }
            }
        }
        catch(Exception throwable){
            Log.e(TAG, "Could not get the table names from db", throwable);
        }
        finally{
            if(c!=null)
                c.close();
        }
        return tables;
    }

    private static void writeCsv(File backupFile, SQLiteDatabase db, List<String> tables){
        CSVWriter csvWrite = null;
        Cursor curCSV = null;
        try {
            csvWrite = new CSVWriter(new FileWriter(backupFile));
            writeSingleValue(csvWrite, DB_BACKUP_DB_VERSION_KEY + "=" + db.getVersion());
            for(String table: tables){
                writeSingleValue(csvWrite, DB_BACKUP_TABLE_NAME + "=" + table);
                curCSV = db.rawQuery("SELECT * FROM " + table,null);
                csvWrite.writeNext(curCSV.getColumnNames());
                while(curCSV.moveToNext()) {
                    int columns = curCSV.getColumnCount();
                    String[] columnArr = new String[columns];
                    for( int i = 0; i < columns; i++){
                        columnArr[i] = curCSV.getString(i);
                    }
                    csvWrite.writeNext(columnArr);
                }
            }
        }
        catch(Exception sqlEx) {
            Log.e(TAG, sqlEx.getMessage(), sqlEx);
        }finally {
            if(csvWrite != null){
                try {
                    csvWrite.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if( curCSV != null ){
                curCSV.close();
            }
        }
    }

    private static void writeSingleValue(CSVWriter writer, String value){
        writer.writeNext(new String[]{value});
    }
}

FileUtils

public class FileUtils {

    public static String getAppDir(){
        return App.getContext().getExternalFilesDir(null) + "/" + App.getContext().getString(R.string.app_name);
    }

    public static File createDirIfNotExist(String path){
        File dir = new File(path);
        if( !dir.exists() ){
            dir.mkdir();
        }
        return dir;
    }

    /* Checks if external storage is available for read and write */
    public static boolean isExternalStorageWritable() {
        String state = Environment.getExternalStorageState();
        return Environment.MEDIA_MOUNTED.equals(state);
    }

    /* Checks if external storage is available to at least read */
    public static boolean isExternalStorageReadable() {
        String state = Environment.getExternalStorageState();
        return Environment.MEDIA_MOUNTED.equals(state) ||
                Environment.MEDIA_MOUNTED_READ_ONLY.equals(state);
    }
}

除了这两个类之外,您要么需要将上下文传递给 FileUtils,要么有一些其他方法来获取上下文。在上面的代码中,App 只是类扩展 Application 以便于访问上下文。

还要记得将Opencsv添加到gradle中,即

compile group: 'com.opencsv', name: 'opencsv', version: '4.1'

然后调用Sqlite导出器类的导出方法即可。

【讨论】:

  • 如何从MainActivity调用这个方法?
  • 您可能希望从后台线程调用导出方法,因为导出数据库可能需要一段时间。为此,您可能需要创建一个 intentService 或其他不阻塞 ui 线程的东西。
  • 我不得不稍作修改。在 createDirIfNotExist 方法中,我不得不将它从“dir.mkdir()”更改为“dir.mkdirs()”,因为我缺少多个父目录。除此之外,它运行良好。
  • 它有效。不过,我还必须将其从“dir.mkdir()”更改为“dir.mkdirs()”。谢谢
  • 无法解析符号“SqliteExporter”,我该怎么办?
【解决方案3】:

首先删除这一行以获得有效的 csv 格式文档。

printWriter.println("FIRST TABLE OF THE DATABASE");

其次,确保表中有数据,并通过调试检查查询是否实际返回任何内容。

【讨论】:

    猜你喜欢
    • 2016-01-21
    • 1970-01-01
    • 2012-05-04
    • 2013-05-13
    • 1970-01-01
    • 2018-12-05
    • 1970-01-01
    • 1970-01-01
    • 2016-01-18
    相关资源
    最近更新 更多