2015-07-12 167 views
10

我想導出SQLite數據到android中的SD卡作爲目錄上的CSV文件。導出SQLite數據庫到csv文件在android中

這就是我一直在下面這個方法,顯然這隻能說明這個文本打印出來:

的數據庫
日期,項目,金額,幣種

在我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"; 

讓我知道你是否需要更多的代碼。

+0

你想要什麼?你是否收到任何錯誤。 – RajSharma

+1

'//在.csv文件中寫入表名和列名稱(以逗號分隔的值)。然後,如果添加表名,則不再是有效的CSV文件。有效CSV文件中的第一行是包含列名稱的標題行,或者它只是第一個數據行。 –

+0

對於您的問題有什麼擔憂......似乎表中沒有數據。 –

回答

21

感謝您的建議傢伙害得我這樣的回答:

private void exportDB() { 
 

 
     File dbFile=getDatabasePath("MyDBName.db"); 
 
     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); 
 
     }

+0

不太清楚從哪裏獲得'getDatabasePath','DBHelper','CSVWriter'和這段代碼的其他部分。 – zygimantus

+0

'getDatabasePath()'方法查找數據庫位置的路徑,'DBHelper'是我的sqlite處理程序類,它擴展了'sqliteOpenHelper','CSVWriter'是CSV函數。代碼直接工作,沒有太多的忙碌。 –

+0

很遺憾你在這裏沒有分享這些課程。他們可能對其他人有用。 – leoneboaventura

1

首先刪除此行以獲得有效的csv格式的文檔。

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

其次,確保您的表中有數據並檢查您的查詢是否實際上通過調試返回任何內容。

1

萬一有人還絆倒了這個問題,我會後我的解決方案,這是稍微超過一般被接受的。你應該能夠通過複製下面的兩個類來導出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}); 
    } 
} 

文件實用程序

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); 
    } 
} 

除了這兩個類,你要麼需要通過上下文的文件實用程序,或者有一些其他的手段獲取上下文。在上面的代碼中,應用程序只是擴展應用程序以便於訪問上下文。

還記得添加Opencsv到搖籃,即

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

然後,只需調用SQLite的出口類出口的方法。

+0

如何從MainActivity調用此方法? – user2872856

+0

你可以用'SqliteExporter.export(db)'調用它,其中db是SQLiteDatabase對象,你可以通過getReadableDatabase()獲取sqliteOpenHelper() – Pete

+0

你可能想從後臺線程中調用export方法,可能需要一段時間才能導出數據庫。爲此,您可能需要創建一個intentService或其他不會阻塞ui線程的其他內容。 – Pete

相關問題