Экспорт базы данных SQLite в файл csv в android
Я пытаюсь экспортировать данные SQLite на SD-карту в android в виде файла CSV в каталоге.
Итак, я пробовал этот метод ниже, и, по-видимому, он отображает только этот текст:
ПЕРВАЯ ТАБЛИЦА БАЗА ДАННЫХ
ДАТА, ITEM, СУММА, ВАЛЮТА
В моем 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 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";
Сообщите мне, если вам нужно больше кода.
Ответы
Ответ 1
Спасибо за ваши предложения, которые привели меня к этому ответу:
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);
}
Ответ 2
Прежде всего удалите эту строку, чтобы иметь действительный документ в формате csv.
printWriter.println("FIRST TABLE OF THE DATABASE");
Во-вторых, убедитесь, что у вас есть данные в вашей таблице и проверьте, действительно ли ваш запрос возвращает что-либо путем отладки.
Ответ 3
Если кто-то все еще наткнется на этот вопрос, я отправлю свое решение, которое немного более общее, чем принятое. Вы должны иметь возможность экспортировать все таблицы в базу данных sqlite почти путем копирования двух классов ниже. Только другие необходимые изменения должны быть связаны с получением контекста приложения и импортом открытых csv.
Некоторые части в значительной степени копируют пасту из других потоков stackoverflow, но я больше не мог их найти.
Sqlite exporter:
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/info/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, либо использовать другие способы получения контекста. В приведенном выше коде приложение - это просто приложение, расширяющее класс для удобного доступа к контексту.
Также не забудьте добавить Opencsv в gradle, т.е.
compile group: 'com.opencsv', name: 'opencsv', version: '4.1'
Затем просто вызовите метод экспорта класса экспортера Sqlite.