【问题标题】:Exporting SQLite Table data as XML将 SQLite 表数据导出为 XML
【发布时间】:2013-01-21 12:41:56
【问题描述】:

我在尝试将我的 SQLite 数据库表导出到 XML 文件时遇到空指针异常。

StackTrace: PasteBin Link

--
更新 2: 我只是不明白传入的内容(在主活动中初始化和调用 exportData 方法时):DatabaseAssistant DA = new DatabaseAssistant(myContext, **WHAT_IS_PASSED_HERE?**); DA.exportData();
--
更新: 提到我在哪里获得 NPE 的行是:com.astix.reachout.DatabaseAssistant.exportData(DatabaseAssistant.java:72 & com.astix.reachout.ReachOutMain$9.onClick(ReachOutMain.java:347)

_exporter.startDbExport( _db.getPath() );DA.exportData() 中可用
--
我提到了this answer。 我的数据库助手代码:

public class DatabaseAssistant
{
    public String filNameFullPath;
    public long filNameTS;
    public String EXPORT_FILE_NAME;
    //private static final String EXPORT_FILE_NAME = "/sdcard/datanaexport.xml";

    private Context _ctx;
    private SQLiteDatabase _db;
    private Exporter _exporter;

    public String newfilename(){
        System.out.println("inside newfilename()");

        filNameTS = System.currentTimeMillis();
        filNameFullPath = Environment.getExternalStorageDirectory().getPath();
        EXPORT_FILE_NAME = filNameFullPath + "/" + filNameTS +".xml";
        System.out.println("new file name: " + EXPORT_FILE_NAME);
        return EXPORT_FILE_NAME;
    }

    public DatabaseAssistant( Context ctx, SQLiteDatabase db )
    {
        _ctx = ctx;
        _db = db;

        newfilename();
        try
        {
            System.out.println("inside try databaseAssitant() -- file name: " + EXPORT_FILE_NAME);
            // create a file on the sdcard to export the
            // database contents to
            File myFile = new File( EXPORT_FILE_NAME );
                        myFile.createNewFile();

                        FileOutputStream fOut =  new FileOutputStream(myFile);
                        BufferedOutputStream bos = new BufferedOutputStream( fOut );

            _exporter = new Exporter( bos );
        }
        catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    public void exportData( )
    {
        log( "Exporting Data" );

        try
        {
            System.out.println("inside try exportData()");
            _exporter.startDbExport( _db.getPath() );

            // get the tables out of the given sqlite database
                    String sql = "SELECT * FROM sqlite_master";

                    Cursor cur = _db.rawQuery( sql, new String[0] );
                    Log.d("db", "show tables, cur size " + cur.getCount() );
                    cur.moveToFirst();

                    String tableName;
                    while ( cur.getPosition() < cur.getCount() )
                    {
                        tableName = cur.getString( cur.getColumnIndex( "name" ) );
                        log( "table name " + tableName );

                        // don't process these two tables since they are used
                        // for metadata
                        if ( ! tableName.equals( "android_metadata" ) &&
                        ! tableName.equals( "sqlite_sequence" ) )
                        {
                            exportTable( tableName );
                        }

                        cur.moveToNext();
                    }
                _exporter.endDbExport();
            _exporter.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    private void exportTable( String tableName ) throws IOException
    {
        _exporter.startTable(tableName);

        // get everything from the table
        String sql = "select * from " + tableName;
        Cursor cur = _db.rawQuery( sql, new String[0] );
        int numcols = cur.getColumnCount();

        log( "Start exporting table " + tableName );

//      // logging
//      for( int idx = 0; idx < numcols; idx++ )
//      {
//          log( "column " + cur.getColumnName(idx) );
//      }

        cur.moveToFirst();

        // move through the table, creating rows
        // and adding each column with name and value
        // to the row
        while( cur.getPosition() < cur.getCount() )
        {
            _exporter.startRow();
            String name;
            String val;
            for( int idx = 0; idx < numcols; idx++ )
            {
                name = cur.getColumnName(idx);
                val = cur.getString( idx );
                log( "col '" + name + "' -- val '" + val + "'" );

                _exporter.addColumn( name, val );
            }

            _exporter.endRow();
            cur.moveToNext();
        }

        cur.close();

        _exporter.endTable();
    }

    private void log( String msg )
    {
        Log.d( "DatabaseAssistant", msg );
    }

    class Exporter
    {
        private static final String CLOSING_WITH_TICK = "'>";
        private static final String START_DB = "<export-database name='";
        private static final String END_DB = "</export-database>";
        private static final String START_TABLE = "<table name='";
        private static final String END_TABLE = "</table>";
        private static final String START_ROW = "<row>";
        private static final String END_ROW = "</row>";
        private static final String START_COL = "<col name='";
        private static final String END_COL = "</col>";

        private BufferedOutputStream _bos;

        public Exporter() throws FileNotFoundException
        {
            this( new BufferedOutputStream(
                    _ctx.openFileOutput( EXPORT_FILE_NAME,
                    Context.MODE_WORLD_READABLE ) ) );
        }

        public Exporter( BufferedOutputStream bos )
        {
            _bos = bos;
        }

        public void close() throws IOException
        {
            if ( _bos != null )
            {
                _bos.close();
            }
        }

        public void startDbExport( String dbName ) throws IOException
        {
            String stg = START_DB + dbName + CLOSING_WITH_TICK;
            _bos.write( stg.getBytes() );
        }

        public void endDbExport() throws IOException
        {
            _bos.write( END_DB.getBytes() );
        }

        public void startTable( String tableName ) throws IOException
        {
            String stg = START_TABLE + tableName + CLOSING_WITH_TICK;
            _bos.write( stg.getBytes() );
        }

        public void endTable() throws IOException
        {
            _bos.write( END_TABLE.getBytes() );
        }

        public void startRow() throws IOException
        {
            _bos.write( START_ROW.getBytes() );
        }

        public void endRow() throws IOException
        {
            _bos.write( END_ROW.getBytes() );
        }

        public void addColumn( String name, String val ) throws IOException
        {
            String stg = START_COL + name + CLOSING_WITH_TICK + val + END_COL;
            _bos.write( stg.getBytes() );
        }
    }

    class Importer
    {

    }

}

在我的主要活动中(在按钮的 onClick 下调用):

DatabaseAssistant DA = new DatabaseAssistant(myContext, mySQLiteDatabase);
DA.exportData();

这里^(上面声明为):

private Context myContext;
private SQLiteDatabase mySQLiteDatabase;

任何建议都是可以理解的.. 谢谢

【问题讨论】:

  • 堆栈跟踪中提到的那一行是哪一行?
  • @CL。您好,感谢您的回复。在我得到 NPE 的地方提到的行是:在 com.astix.reachout.DatabaseAssistant.exportData(DatabaseAssistant.java:72 & com.astix.reachout.ReachOutMain$9.onClick(ReachOutMain.java:347) 其中 _exporter.startDbExport( _db.getPath() ); 在 @ 内可用987654332@
  • 此信息不属于评论,而是属于您的问题。
  • @CL。 StackTrace 提到了同样的事情。请参阅问题描述中的链接。 :|将使用此信息更新我的问题。太 :) 更新请查看我更新的问题。
  • 所以有2个嫌疑人:_exporter,_db。其中之一或两者都为空。你能检查一下吗?

标签: java android xml sqlite android-sqlite


【解决方案1】:

_exporter_dbnull

您的构造函数初始化了这两个变量,所以很可能给构造函数的mySQLiteDatabase 已经是null。 (尽管如果构造函数中发生任何错误,您得到一个无效的_exporter;最好抑制异常并继续进行,就好像什么都没发生一样。这里不是这种情况,因为没有堆栈跟踪。)

【讨论】:

  • +1 是的,_db 为空。我怀疑这是由于传递的参数不正确,例如://在我的主要活动中(在按钮的 onClick 下调用):DatabaseAssistant DA = new DatabaseAssistant(myContext, mySQLiteDatabase); DA.exportData(); //上面声明为:private Context myContext; private SQLiteDatabase mySQLiteDatabase; 实际上根据发布的答案@ 987654321@在线DatabaseAssistant DA = new DatabaseAssistant(myContext, mySQLiteDatabase);
  • (续)什么是 mySQLiteDatabase);应该是?我尝试在我的 DBAdapter 类的对象中设置处理所有数据库访问,但它没有帮助。另外,我尝试了我的数据库名称也不起作用。我知道这是一个愚蠢的问题,但只是卡住了:| (这也是我在该答案中发布的相同评论,但无法得到回复)
  • 我只是不明白传入的内容:DatabaseAssistant DA = new DatabaseAssistant(myContext, **WHAT_IS_PASSED_HERE?**); DA.exportData();
  • +1 来自上述链接You can then get an instance of your SQLiteOpenHelper implementation using the constructor you've defined. To write to and read from the database, call getWritableDatabase() and getReadableDatabase(), respectively. These both return a SQLiteDatabase object that represents the database and provides methods for SQLite operations.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-05
  • 1970-01-01
  • 2016-01-18
  • 2014-01-23
  • 1970-01-01
相关资源
最近更新 更多