为了账号安全,请及时绑定邮箱和手机立即绑定

是否有任何方法可以帮助解决常见的SQLite问题?

是否有任何方法可以帮助解决常见的SQLite问题?

慕妹3146593 2019-07-04 17:57:50
是否有任何方法可以帮助解决常见的SQLite问题?通常,相对简单的错误会导致一些问题,而这些问题往往由于对SQLite的误解而更加复杂。例如:-表和列未找到,因为通常假定onCreatea的方法DBHelper的子类SQLiteOpenHelper类)每次创建DBHelper实例或每次运行应用程序时运行。(注意!onCreate只有在第一次创建数据库时才自动调用,然后才在尝试使用SQLiteDatabase getReadableDatabase或getWriteableDatabse方法,如果更改数据库结构/模式,则有三种简单的强制方法onCreate若要运行,a)清除应用程序的数据,b)卸载App或b),如果onUpgrade方法调用onCreate方法(在删除表后),然后增加数据库版本号。插入/更新不工作但没有失败。对于SQLite的新手来说,它也可能令人恼火/令人望而生畏,因为它无法很容易地看到数据库包含的内容。那么,是否有任何通用的实用程序可以提供帮助呢?注意!这是一个关于分享知识问答风格.
查看完整描述

3 回答

?
呼唤远方

TA贡献1856条经验 获得超11个赞

以下是新手可能会发现有用的一些通用实用程序,它们被设计为非特定的,并且可以在任何数据库/表上工作。

目前有下列可能有用的方法:

  • getAllRowsFromTable

    若要使用所有行撤回游标,请执行以下操作。
  • logCursorColumns

    若要将光标中的列写入日志,请执行以下操作。
  • logCursorData

    若要将光标数据和列写入日志,请执行以下操作。

注意!关于增加/修正的请求/建议肯定会得到考虑。

此外,还使用了上述方法或用于测试/创建上述内容的方法:

  • getEmptyColumnLessCursor (使用这种方法的100分 :) ).

  • getBytedata

    返回给定字节数组的十六进制字符串(用于BLOB处理)。
  • convertBytesToHex

    将字节数组转换为十六进制字符串(用于BLOB处理)。

getAllRowsFromTable

预期的用途是创建一个游标,随后由logCursorColumnslogCursorData方法。这不应该在生产应用程序中使用(而不是不能使用)。

这个签名是:-

public static Cursor getAllRowsFromTable(
                                  SQLiteDatabase db,
                                  String tablename,
                                  boolean use_error_checking,
                                  String forceRowidAs)

地点:-

  • 第一个参数是SQLite数据库(由于一般性质而需要)。
  • 第二个参数是获取数据的表名。
  • 如果表不在数据库中,则在创建写入日志的游标之前,第三个参数(如果为true)将检查表是否存在。
  • 第四个参数(如果不为NULL或长度>0的字符串)将创建一个附加列,该列将根据带有ROWID内容的参数命名(用于在未提供ROWID别名而因此不包括ROWID时提供帮助)。

    什么是ROWID?

示例用法:-

    mEventsDBHelper = new EventsDBHelper(this);


    // Get all rows from table (this exist or should do)
    Cursor events = CommonSQLiteUtilities.getAllRowsFromTable(
            mEventsDBHelper.getEventsDB(),
            EventsDBHelper.TBNAME,
            CommonSQLiteUtilities.ERROR_CHECKING_ON,
            null
    );

    // Deisgned to be problematic i.e. no such table        
    Cursor ooops = CommonSQLiteUtilities.getAllRowsFromTable(
            mEventsDBHelper.getEventsDB(),
            "NOTATABLE",
            CommonSQLiteUtilities.ERROR_CHECKING_ON,
            "rumplestiltskin"
    );
  • 第二次调用导致日志中的以下行:

    D/SQLITE_CSU: Table NOTATABLE was not located in the SQLite Database Master Table.
  • 将始终返回游标,尽管该游标可能没有行,也没有列(例如,在表不在数据库的情况下)。

  • 当查询数据库表时(如果是的话),将捕获和报告异常。例如指定作为第四个参数(有效地尝试使用ROWID AS IS,而SQLIte不喜欢,则会产生类似于以下内容的结果:-


10-09 18:57:52.591 3835-3835/? E/SQLiteLog: (1) near "IS": syntax error
10-09 18:57:52.592 3835-3835/? D/SQLITE_CSU: Exception encountered but trapped when querying table events Message was: 
                                             
   near "IS": syntax error (code 1): , while compiling: SELECT rowid AS  IS , * FROM events
10-09 18:57:52.592 3835-3835/? D/SQLITE_CSU: Stacktrace was:
10-09 18:57:52.592 3835-3835/? W/System.err: android.database.sqlite.SQLiteException: near "IS": syntax error (code 1): ,
 while compiling: SELECT rowid AS  IS , * FROM events
10-09 18:57:52.592 3835-3835/? W/System.err:     at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
10-09 18:57:52.592 3835-3835/? W/System.err:     
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:889)
10-09 18:57:52.592 3835-3835/? W/System.err:     at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:500)
10-09 18:57:52.592 3835-3835/? W/System.err:     at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
10-09 18:57:52.592 3835-3835/? W/System.err:     at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
10-09 18:57:52.592 3835-3835/? W/System.err:     at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
10-09 18:57:52.592 3835-3835/? W/System.err:     at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:44)
10-09 18:57:52.592 3835-3835/? W/System.err:     at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1316)
10-09 18:57:52.592 3835-3835/? W/System.err:     at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1163)
10-09 18:57:52.592 3835-3835/? W/System.err:     at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1034)
10-09 18:57:52.592 3835-3835/? W/System.err:     at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1202)
10-09 18:57:52.592 3835-3835/? W/System.err:     
at mjt.sqlitedbexamples.CommonSQLiteUtilities.getAllRowsFromTable(CommonSQLiteUtilities.java:97)
10-09 18:57:52.592 3835-3835/? W/System.err:     at mjt.sqlitedbexamples.MainActivity.onCreate(MainActivity.java:61)
10-09 18:57:52.593 3835-3835/? W/System.err:     at android.app.Activity.performCreate(Activity.java:5990)
10-09 18:57:52.593 3835-3835/? W/System.err:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
10-09 18:57:52.593 3835-3835/? W/System.err:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
10-09 18:57:52.593 3835-3835/? W/System.err:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
10-09 18:57:52.593 3835-3835/? W/System.err:     at android.app.ActivityThread.access$800(ActivityThread.java:151)
10-09 18:57:52.593 3835-3835/? W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
10-09 18:57:52.593 3835-3835/? W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:102)
10-09 18:57:52.593 3835-3835/? W/System.err:     at android.os.Looper.loop(Looper.java:135)
10-09 18:57:52.593 3835-3835/? W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5254)
10-09 18:57:52.593 3835-3835/? W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
10-09 18:57:52.593 3835-3835/? W/System.err:     at java.lang.reflect.Method.invoke(Method.java:372)
10-09 18:57:52.593 3835-3835/? W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
10-09 18:57:52.593 3835-3835/? W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
  • 返回的游标将为空,没有行或列。

logCursorColumns

用于编写有关游标的列信息(这些信息通常反映数据库,特别是如果使用getAllRowsFromTable).

这个签名是:-

    public static void logCursorColumns(Cursor csr)

地点:-

  • 第一个参数是游标(任意游标)。

示例用法:-

注意!继续前面的示例。

    CommonSQLiteUtilities.logCursorColumns(events);
    CommonSQLiteUtilities.logCursorColumns(ooops);

这将产生以下方面的产出:-

10-09 18:57:52.593 3835-3835/? D/SQLITE_CSU: logCursorColumns invoked. Cursor has the following 8 columns.
10-09 18:57:52.593 3835-3835/? D/SQLITE_CSU: Column Name 1 is _id
10-09 18:57:52.593 3835-3835/? D/SQLITE_CSU: Column Name 2 is starts
10-09 18:57:52.593 3835-3835/? D/SQLITE_CSU: Column Name 3 is starts_timestamp
10-09 18:57:52.593 3835-3835/? D/SQLITE_CSU: Column Name 4 is ends
10-09 18:57:52.593 3835-3835/? D/SQLITE_CSU: Column Name 5 is ends_timestamp
10-09 18:57:52.593 3835-3835/? D/SQLITE_CSU: Column Name 6 is description
10-09 18:57:52.593 3835-3835/? D/SQLITE_CSU: Column Name 7 is counter
10-09 18:57:52.593 3835-3835/? D/SQLITE_CSU: Column Name 8 is bytedata
10-09 18:57:52.593 3835-3835/? D/SQLITE_CSU: logCursorColumns invoked. Cursor has the following 0 columns.

logCursorData

这非常类似于logCursorColumns除此之外,它还提供了更广泛的信息重新分级列,并且还提供了重新分级存储在数据库中的实际数据的信息。

这个签名是:-

    public static void logCursorData(Cursor csr)

地点:-

  • 第一个参数是游标(任意游标)。

示例用法:-

注意!继续前面的示例。

    CommonSQLiteUtilities.logCursorData(events);
    CommonSQLiteUtilities.logCursorData(ooops);

这将产生以下方面的产出:-

10-09 19:30:31.801 1455-1455/? D/SQLITE_CSU: logCursorData Cursor has 6 rows with 8 columns.

10-09 19:30:31.801 1455-1455/? D/SQLITE_CSU: Information for row 1 offset=0

                                                For Column _id Type is INTEGER value as String is 1 value as long is 1 value as double is 1.0

                                                For Column starts Type is INTEGER value as String is 1507537831 value as long is 1507537831 value as double is 1.507537831E9

                                                For Column starts_timestamp Type is INTEGER value as String is 1507537831783 value as long is 1507537831783 value as double is 1.507537831783E12

                                                For Column ends Type is INTEGER value as String is 0 value as long is 0 value as double is 0.0

                                                For Column ends_timestamp Type is INTEGER value as String is 0 value as long is 0 value as double is 0.0

                                                For Column description Type is STRING value as String is TESTEVENT 001 just description value as long is 0 value as double is 0.0

                                                For Column counter Type is INTEGER value as String is 0 value as long is 0 value as double is 0.0

                                                For Column bytedata Type is BLOB value as String is unobtainable! value as long is unobtainable! value as double is unobtainable! value as blob is 00000000

10-09 19:30:31.802 1455-1455/? D/SQLITE_CSU: Information for row 2 offset=1

                                                For Column _id Type is INTEGER value as String is 2 value as long is 2 value as double is 2.0

                                                For Column starts Type is INTEGER value as String is 1507537831 value as long is 1507537831 value as double is 1.507537831E9

                                                For Column starts_timestamp Type is INTEGER value as String is 1507537831785 value as long is 1507537831785 value as double is 1.507537831785E12

                                                For Column ends Type is INTEGER value as String is 0 value as long is 0 value as double is 0.0

                                                For Column ends_timestamp Type is INTEGER value as String is 0 value as long is 0 value as double is 0.0

                                                For Column description Type is STRING value as String is TESTEVENT 002 description and bytearray value as long is 0 value as double is 0.0

                                                For Column counter Type is INTEGER value as String is 0 value as long is 0 value as double is 0.0

                                                For Column bytedata Type is BLOB value as String is unobtainable! value as long is unobtainable! value as double is unobtainable! value as blob is 0001020304050607080900

10-09 19:30:31.802 1455-1455/? D/SQLITE_CSU: Information for row 3 offset=2

                                                For Column _id Type is INTEGER value as String is 3 value as long is 3 value as double is 3.0

                                                For Column starts Type is INTEGER value as String is 1507537831 value as long is 1507537831 value as double is 1.507537831E9

                                                For Column starts_timestamp Type is INTEGER value as String is 1507537831789 value as long is 1507537831789 value as double is 1.507537831789E12

                                                For Column ends Type is INTEGER value as String is 15254678 value as long is 15254678 value as double is 1.5254678E7

                                                For Column ends_timestamp Type is INTEGER value as String is 0 value as long is 0 value as double is 0.0

                                                For Column description Type is STRING value as String is TESTEVENT 003 desc, bytes and endint value as long is 0 value as double is 0.0

                                                For Column counter Type is INTEGER value as String is 0 value as long is 0 value as double is 0.0

                                                For Column bytedata Type is BLOB value as String is unobtainable! value as long is unobtainable! value as double is unobtainable! value as blob is 7F7E7D7C

10-09 19:30:31.802 1455-1455/? D/SQLITE_CSU: Information for row 4 offset=3

                                                For Column _id Type is INTEGER value as String is 4 value as long is 4 value as double is 4.0

                                                For Column starts Type is INTEGER value as String is 1507537831 value as long is 1507537831 value as double is 1.507537831E9

                                                For Column starts_timestamp Type is INTEGER value as String is 1507537831792 value as long is 1507537831792 value as double is 1.507537831792E12

                                                For Column ends Type is INTEGER value as String is 0 value as long is 0 value as double is 0.0

                                                For Column ends_timestamp Type is INTEGER value as String is 0 value as long is 0 value as double is 0.0

                                                For Column description Type is STRING value as String is TESTEVENT 004 desc, bytes and endlong value as long is 0 value as double is 0.0

                                                For Column counter Type is INTEGER value as String is 0 value as long is 0 value as double is 0.0

                                                For Column bytedata Type is BLOB value as String is unobtainable! value as long is unobtainable! value as double is unobtainable! value as blob is 38424C56606A747E

10-09 19:30:31.803 1455-1455/? D/SQLITE_CSU: Information for row 5 offset=4

                                                For Column _id Type is INTEGER value as String is 5 value as long is 5 value as double is 5.0

                                                For Column starts Type is INTEGER value as String is 1507537831 value as long is 1507537831 value as double is 1.507537831E9

                                                For Column starts_timestamp Type is INTEGER value as String is 1507537831794 value as long is 1507537831794 value as double is 1.507537831794E12

                                                For Column ends Type is INTEGER value as String is 1699999999 value as long is 1699999999 value as double is 1.699999999E9

                                                For Column ends_timestamp Type is INTEGER value as String is 0 value as long is 0 value as double is 0.0

                                                For Column description Type is STRING value as String is TESTEVENT 005 desc, endint value as long is 0 value as double is 0.0

                                                For Column counter Type is INTEGER value as String is 0 value as long is 0 value as double is 0.0

                                                For Column bytedata Type is BLOB value as String is unobtainable! value as long is unobtainable! value as double is unobtainable! value as blob is 00000000

10-09 19:30:31.803 1455-1455/? D/SQLITE_CSU: Information for row 6 offset=5

                                                For Column _id Type is INTEGER value as String is 6 value as long is 6 value as double is 6.0

                                                For Column starts Type is INTEGER value as String is 1507537831 value as long is 1507537831 value as double is 1.507537831E9

                                                For Column starts_timestamp Type is INTEGER value as String is 1507537831796 value as long is 1507537831796 value as double is 1.507537831796E12

                                                For Column ends Type is INTEGER value as String is 0 value as long is 0 value as double is 0.0

                                                For Column ends_timestamp Type is INTEGER value as String is 0 value as long is 0 value as double is 0.0

                                                For Column description Type is STRING value as String is TESTEVENT 006 desc, endlong value as long is 0 value as double is 0.0

                                                For Column counter Type is INTEGER value as String is 0 value as long is 0 value as double is 0.0

                                                For Column bytedata Type is BLOB value as String is unobtainable! value as long is unobtainable! value as double is unobtainable! value as blob is 00000000


对于空游标(OOOPS):-

10-09 19:30:31.804 1455-1455/? D/SQLITE_CSU: logCursorData Cursor has 0 rows with 0 columns.

代码CommonSQLiteUutities.java:-

public class CommonSQLiteUtilities {

    public static final boolean ERROR_CHECKING_ON = true;
    public static final boolean ERROR_CHECKING_OFF = false;

    // SQLite MASTER TABLE definitions
    static final String SQLITE_MASTER = "sqlite_master";
    static final String SM_TABLE_TYPE_COLUMN = "type";
    static final String SM_NAME_COLUMN = "name";
    static final String SM_TABLENAME_COLUMN = "tbl_name";
    static final String SM_ROOTPAGE_COLUMN = "rootpage";
    static final String SM_SQL_COLUMN = "sql";
    static final String SM_TYPE_TABLE = "table";
    static final String SM_TYPE_INDEX = "index";


    static final String CSU_TAG = "SQLITE_CSU";

    private CommonSQLiteUtilities() {}

    /**
     * Generic get all rows from an SQlite table,
     * allowing the existence of the table to be checked and also
     * allowing the ROWID to be added AS a supplied string
     *
     * @param db                    The SQLiteDatabase
     * @param tablename             The name of the table from which the
     *                              returned cursor will be created from;
     *                              Note!
     * @param use_error_checking    Whether ot not to try to detect errors
     *                              currently just table doesn't exist,
     *                              true to turn on, false to turn off
     *                              ERROR_CHECKING_ON = true
     *                              ERROR_CHECKING_OFF = false
     * @param forceRowidAs          If length of string passed is 1 or greater
     *                              then a column, as an alias of ROWID, will be
     *                              added to the cursor
     * @return                      the extracted cursor, or in the case of the
     *                              underlying table not existing an empty cursor
     *                              with no columns
     */
    public static Cursor getAllRowsFromTable(SQLiteDatabase db,
                                      String tablename,
                                      boolean use_error_checking,
                                      String forceRowidAs) {
        String[] columns = null;

        // Tablename must be at least 1 character in length
        if (tablename.length() < 1) {
            Log.d(CSU_TAG,new Object(){}.getClass().getEnclosingMethod().getName() +
                    " is finishing as the provided tablename is less than 1 character in length"
            );
            return new MatrixCursor(new String[]{});
        }

        // If use_error_checking is true then check that the table exists
        // in the sqlite_master table
        if (use_error_checking) {
            Cursor chkcsr = db.query(SQLITE_MASTER,null,
                    SM_TABLE_TYPE_COLUMN + "=? AND "
                            + SM_TABLENAME_COLUMN + "=?",
                    new String[]{SM_TYPE_TABLE,tablename},
                    null,null,null
            );

            // Ooops table is not in the Database so return an empty
            // column-less cursor
            if (chkcsr.getCount() < 1) {
                Log.d(CSU_TAG,"Table " + tablename +
                        " was not located in the SQLite Database Master Table."
                );
                // return empty cursor with no columns
                return new MatrixCursor(new String[]{});

            }
            chkcsr.close();
        }

        // If forcing an alias of ROWID then user ROWID AS ???, *
        if(forceRowidAs != null && forceRowidAs.length() > 0) {
            columns = new String[]{"rowid AS " +forceRowidAs,"*"};
        }

        // Finally return the Cursor but trap any exceptions
        try {
            return db.query(tablename, columns, null, null, null, null, null);
        } catch (Exception e) {
            Log.d(CSU_TAG,"Exception encountered but trapped when querying table " + tablename +
                    " Message was: \n" + e.getMessage());
            Log.d(CSU_TAG,"Stacktrace was:");
            e.printStackTrace();
            return new MatrixCursor(new String[]{});
        }
    }

    /**
     * Create and return a Cursor devoid of any rows and columns
     * Not used, prehaps of very little use.
     * @param db    The Sqlite database in which the cursor is to be created
     * @return      The empty Cursor
     */
    private static Cursor getEmptyColumnLessCursor(SQLiteDatabase db) {
        return new MatrixCursor(new String[]{});
    }

    /**
     * Write column names in the passed Cursor to the log
     * @param csr   The Cursor to be inspected.
     */
    public static void logCursorColumns(Cursor csr) {
        Log.d(CSU_TAG,
                new Object(){}.getClass().getEnclosingMethod().getName() +
                        " invoked. Cursor has the following " +
                        Integer.toString(csr.getColumnCount())+
                        " columns.");
        int position = 0;
        for (String column: csr.getColumnNames()) {
            position++;
            Log.d(CSU_TAG,"Column Name " +
                    Integer.toString(position) +
                    " is "
                    + column
            );
        }
    }

    /**
     * Write the contents of the Cursor to the log
     * @param csr   The Cursor that is to be displayed in the log
     */
    public static void logCursorData(Cursor csr) {
        int columncount = csr.getColumnCount();
        int rowcount = csr.getCount();
        int csrpos = csr.getPosition(); //<<< added 20171016 to
        Log.d(CSU_TAG,
                new Object(){}.getClass().getEnclosingMethod().getName() +
                        " Cursor has " +
                        Integer.toString(rowcount) +
                        " rows with " +
                        Integer.toString(columncount) + " columns."
        );
        csr.moveToPosition(-1);     //Ensure that all rows are retrieved <<< added 20171016
        while (csr.moveToNext()) {
            String unobtainable = "unobtainable!";
            String logstr = "Information for row " + Integer.toString(csr.getPosition() + 1) + " offset=" +
             Integer.toString(csr.getPosition());
            for (int i=0; i < columncount;i++) {
                logstr = logstr + "\n\tFor Column " + csr.getColumnName(i);
                switch (csr.getType(i)) {
                    case Cursor.FIELD_TYPE_NULL:
                        logstr = logstr + " Type is NULL";
                        break;
                    case Cursor.FIELD_TYPE_FLOAT:
                        logstr = logstr + "Type is FLOAT";
                        break;
                    case Cursor.FIELD_TYPE_INTEGER:
                        logstr = logstr + " Type is INTEGER";
                        break;
                    case Cursor.FIELD_TYPE_STRING:
                        logstr = logstr + " Type is STRING";
                        break;
                    case Cursor.FIELD_TYPE_BLOB:
                        logstr = logstr + " Type is BLOB";
                        break;
                }
                String strval_log = " value as String is ";
                String lngval_log = " value as long is ";
                String dblval_log = " value as double is ";
                String blbval_log = "";
                try {
                    strval_log = strval_log + csr.getString(i);
                    lngval_log = lngval_log + csr.getLong(i);
                    dblval_log = dblval_log +  csr.getDouble(i);
                } catch (Exception e) {
                    strval_log = strval_log + unobtainable;
                    lngval_log = lngval_log + unobtainable;
                    dblval_log = dblval_log + unobtainable;
                    try {
                        blbval_log = " value as blob is " +
                                getBytedata(csr.getBlob(i),24);
                    } catch (Exception e2) {
                        e2.printStackTrace();
                    }

                }
                logstr = logstr + strval_log + lngval_log + dblval_log + blbval_log;
            }
            Log.d(CSU_TAG,logstr);
        }
        csr.moveToPosition(csrpos); // restore cursor position <<< added 20171016
    }

    /**
     * Return a hex string of the given byte array
     * @param bytes     The byte array to be converted to a hexadecimal string
     * @param limit     the maximum number of bytes;
     *                  note returned string will be up to twice as long
     * @return          The byte array represented as a hexadecimal string
     */
    private static String getBytedata(byte[] bytes, int limit) {
        if (bytes.length < limit) {
            return convertBytesToHex(bytes);
        } else {
            byte[] subset = new byte[limit];
            System.arraycopy(bytes,0,subset,0,limit);
            return convertBytesToHex(subset);
        }
    }

    // HEX characters as a char array for use by convertBytesToHex
    private final static char[] hexarray = "0123456789ABCDEF".toCharArray();

    /**
     * Return a hexadecimal string representation of the passed byte array
     * @param bytes     The byte array to be represented.
     * @return          The string representing the byte array as hexadecimal
     */
    private static String convertBytesToHex(byte[] bytes) {
        char[] hexstr = new char[bytes.length * 2];
        for (int i=0; i < bytes.length; i++) {
            int h = bytes[i] & 0xFF;
            hexstr[i * 2] = hexarray[h >>> 4];
            hexstr[i * 2 + 1] = hexarray[h & 0xF];
        }
        return new String(hexstr);
    }
}

要使用代码,只需创建CommonSQLite实用程序类并复制上面的代码。


查看完整回答
反对 回复 2019-07-04
  • 3 回答
  • 0 关注
  • 507 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信