Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/210.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在android中从sqlite数据库中存储的blob打开pdf?_Java_Android_Sqlite_Pdf_Blob - Fatal编程技术网

Java 如何在android中从sqlite数据库中存储的blob打开pdf?

Java 如何在android中从sqlite数据库中存储的blob打开pdf?,java,android,sqlite,pdf,blob,Java,Android,Sqlite,Pdf,Blob,在我的应用程序中,我希望能够打开到我的sqlite数据库的连接,并检索包含id、名称和blob(pdf的字节[])的单行。我该怎么做呢 MainActivity.class负责所有工作。它将我的资产文件夹中的pdf转换为字节数组,我将其作为blob存储在SQLite数据库中。但是,当我打开文件时,文件中没有数据 谁能帮我解决我在这里做错了什么 我的主要活动: public class MainActivity extends Activity { //---------------------

在我的应用程序中,我希望能够打开到我的sqlite数据库的连接,并检索包含id、名称和blob(pdf的字节[])的单行。我该怎么做呢

MainActivity.class负责所有工作。它将我的资产文件夹中的pdf转换为字节数组,我将其作为blob存储在SQLite数据库中。但是,当我打开文件时,文件中没有数据

谁能帮我解决我在这里做错了什么

我的主要活动:

public class MainActivity extends Activity {

//-------------------------------------------------------------------
// Member Variables
//-------------------------------------------------------------------

// UI components
private Button mViewPDFButton           = null;
private TextView mDirectionsTextView    = null;

// File name of the PDF we want to store 
private final String FILE_NAME      = "my-pdf-file.pdf";
private InputStream inputStream;
private byte [] pdfFileArray        = null;
private PDFDbAdapter pdfAdapter     = null;
private ByteArrayOutputStream buffer;

// Directions
private String text = "To view a PDF from internal storage, click the \'View PDF\' button on the bottom of the screen.";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Initialize the UI
    mViewPDFButton      = (Button) findViewById(R.id.ViewPDFButton);
    mDirectionsTextView = (TextView) findViewById(R.id.directionsTextView);

    // Set the Text for the directions
    mDirectionsTextView.setText(text);

    // Call to Copy the File to the Internal Storage
    copyFileToDatabase(FILE_NAME);

    // Add a listener to the button
    mViewPDFButton.setOnClickListener(ViewPDFListener);





}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

//-----------------------------------------------------------------------------------
// Private Methods
//-----------------------------------------------------------------------------------
private void copyFileToDatabase(String fileName){

    // Get the Application Assets from the asset manager
    AssetManager assetManager = getBaseContext().getAssets();

    // Attempt to process the file input stream
    try{
        // use the asset manager to open the file
        inputStream = assetManager.open(fileName);

        // Initialize the adapter reference using the base context
        pdfAdapter = new PDFDbAdapter(getBaseContext());
        pdfAdapter.open();

        // Create the byte array from the input stream
        pdfFileArray = convertToByteArray(inputStream);

        // Store the byte array in the database
        pdfAdapter.createPDFFile(fileName, pdfFileArray);

    }catch(IOException ex){

        // Print the stack trace from the exception
        ex.printStackTrace();
    }

}

// Launch the new Intent with the file stored in the DB
private void launchPDFIntent(){

    // Initialize the Cursor for the adapter
    Cursor cursor = pdfAdapter.fetchPDFFile(0);

    // Move the cursor to the first position
    cursor.moveToPosition(0);

    // create a String to hold the current File name
    String fileName;

    // Create a byte array to hold the array returned from the cursor
    byte [] blobArray = null;

    // Loop through using the cursor
    while(cursor.moveToNext()){

        // Get the id from the cursor
        int id = cursor.getInt(0);

        // get the file name from the cursor
        fileName = cursor.getString(1);

        // get the array from the cursor
        blobArray = cursor.getBlob(2);
    }

    // Create a new file from the returned byte array
    File pdfFile = convertBytesToFile(blobArray);

    Uri path = Uri.fromFile(pdfFile);

    // Parse the file into a uri to share with another application

    Intent newIntent = new Intent(Intent.ACTION_VIEW);
    newIntent.setDataAndType(path, "application/pdf");
    newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

    try{
        startActivity(newIntent);
    }catch(ActivityNotFoundException ex){
        ex.printStackTrace();
    }

}

// Converts the array of bytes into a File
private File convertBytesToFile(byte [] byteToConvert){

    File fileToReturn = new File( Environment.getExternalStorageDirectory() + "/PDF-doc.pdf");

    try{

        FileOutputStream fileOutputStream = new FileOutputStream(fileToReturn);
        fileOutputStream.write(byteToConvert);
        fileOutputStream.close();

    }catch(FileNotFoundException ex){
        ex.printStackTrace();
    }catch(Exception ex){
        ex.printStackTrace();
    }

    return fileToReturn;
}


// Converts the pdf file from assets to a byte array for storage in the database
private byte[] convertToByteArray(InputStream input){
    int nRead = 0;
    byte [] convertedData = new byte[16384];
    buffer = new ByteArrayOutputStream();

    try{

        // Read the data into the array
        while((nRead = input.read(convertedData, 0, convertedData.length)) != -1){
            buffer.write(convertedData, 0, nRead);
        }

        // Flush the buffer
        buffer.flush();


    }catch(IOException ex){
        ex.printStackTrace();
        return null;
    }

return buffer.toByteArray();
}


//-----------------------------------------------------------------------------------
// Actions
//-----------------------------------------------------------------------------------

// Listener for the button to view the PDF
private OnClickListener ViewPDFListener = new OnClickListener(){

    @Override
    public void onClick(View arg0) {

        launchPDFIntent();

    }

};

}
更新-以下是最终对我有效的活动。这演示了一些可能应该在单独的类中完成的事情。此文件从assets文件夹复制pdf并将其作为blob存储到db中,然后单击按钮从db中检索blob,并为任何此类应用程序启动任何操作视图意图。希望这对别人有帮助,我花了一点时间才把它做好

public class MainActivity extends Activity {

//-------------------------------------------------------------------
// Member Variables
//-------------------------------------------------------------------

private static final String TAG = "PDFViewer";

// UI components
private Button mViewPDFButton           = null;
private TextView mDirectionsTextView    = null;

// File name of the PDF we want to store 
private final String FILE_NAME      = "my-pdf-file.pdf";
private InputStream inputStream;
private byte [] pdfFileArray        = null;
private PDFDbAdapter pdfAdapter     = null;
private ByteArrayOutputStream buffer;
private String fileName;

// Directions
private String text = "To view a PDF from internal storage, click the \'View PDF\' button on the bottom of the screen.";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Initialize the UI
    mViewPDFButton      = (Button) findViewById(R.id.ViewPDFButton);
    mDirectionsTextView = (TextView) findViewById(R.id.directionsTextView);

    // Set the Text for the directions
    mDirectionsTextView.setText(text);

    // Call to Copy the File to the Internal Storage
    copyFileToDatabase(FILE_NAME);

    // Add a listener to the button
    mViewPDFButton.setOnClickListener(ViewPDFListener);

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

//-----------------------------------------------------------------------------------
// Private Methods
//-----------------------------------------------------------------------------------
private void copyFileToDatabase(String fileName){

    // Get the Application Assets from the asset manager
    AssetManager assetManager = getBaseContext().getAssets();

    // Attempt to process the file input stream
    try{
        // use the asset manager to open the file
        inputStream = assetManager.open(fileName);

        // Initialize the adapter reference using the base context
        pdfAdapter = new PDFDbAdapter(getBaseContext());
        pdfAdapter.open();

        // Create the byte array from the input stream
        pdfFileArray = convertToByteArray(inputStream);

        // flush the buffer, since the operation is complete
        buffer.flush();

        // Store the byte array in the database
        pdfAdapter.createPDFFile(fileName, pdfFileArray);

    }catch(IOException ex){

        // Print the stack trace from the exception
        ex.printStackTrace();
    }

    pdfAdapter.close();

}

// Launch the new Intent with the file stored in the DB
private void launchPDFIntent(){

    pdfAdapter = new PDFDbAdapter(getBaseContext());
    pdfAdapter.open();

    // Initialize the Cursor for the adapter
    Cursor cursor = pdfAdapter.fetchPDFFile(1);

    // Move the cursor to the first position
    cursor.moveToFirst();

    // Create a byte array to hold the array returned from the cursor
    byte [] blobArray = null;

    // Get the id from the cursor
    int id = cursor.getInt(0);

    // get the file name from the cursor
    fileName = cursor.getString(1);

    // get the array from the cursor
    blobArray = cursor.getBlob(2);
    Log.d("PDF_SIZE", "The array is: "+ blobArray.length);


    // Create a new file from the returned byte array
    File pdfFile = convertBytesToFile(blobArray);

    // The unique identifier for the file
    Uri path = Uri.fromFile(pdfFile);

    // Parse the file into a uri to share with another application

    Intent newIntent = new Intent(Intent.ACTION_VIEW);
    newIntent.setDataAndType(path, "application/pdf");
    newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

    try{
        startActivity(newIntent);
    }catch(ActivityNotFoundException ex){
        ex.printStackTrace();
    }

    pdfAdapter.close();
}
以及处理db操作的我的适配器类:

public class PDFDbAdapter {

// -------------------------------------------------------------------
// Constants
// -------------------------------------------------------------------

public static final String DATABASE_TABLE = "pdf_documents";
public static final String KEY_ROW_ID = "_id";
public static final String KEY_FILE_NAME = "file_name";
public static final String KEY_FILE_BLOB = "file_blob";


static final String CREATE_TABLE_PDFDOCS = ("CREATE TABLE " + DATABASE_TABLE + "(" 
                                                + KEY_ROW_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
                                                + KEY_FILE_NAME + " VARCHAR(100),"
                                                + KEY_FILE_BLOB + " BLOB);");

// -------------------------------------------------------------------
// Member Variables
// -------------------------------------------------------------------
private Context mContext;
private DBCache mDbHelper;
private SQLiteDatabase mDataBase;

// -------------------------------------------------------------------
// Constructor

// Constructor, passes in the current context of the application
public PDFDbAdapter(Context context){
    this.mContext = context;
}

// -------------------------------------------------------------------
// Class Methods

// Open the Database for reading
public PDFDbAdapter open() throws SQLiteException{
    this.mDbHelper = new DBCache(mContext);
    this.mDataBase = mDbHelper.getWritableDatabase();

    return this;
}

// Create the new PDF File save in the database
public long createPDFFile(String fileName, byte [] fileBlob){
    ContentValues values = new ContentValues();
    values.put(KEY_FILE_NAME, fileName);
    values.put(KEY_FILE_BLOB, fileBlob);

    return this.mDataBase.insert(DATABASE_TABLE, null, values);
}

// Read the current file in the database
public Cursor fetchPDFFile(long rowId){

    Cursor currentCursor = mDataBase.query(true, DATABASE_TABLE, new String [] {KEY_ROW_ID, KEY_FILE_NAME, KEY_FILE_BLOB},
            KEY_ROW_ID +"="+rowId, null, null, null, null, null);

    if(currentCursor != null){
        currentCursor.moveToFirst();
    }

    return currentCursor;

}

// Read all available PDF's from the database
public Cursor fetchAllPDFFiles(){
    return this.mDataBase.query( DATABASE_TABLE, new String [] {KEY_ROW_ID, KEY_FILE_NAME, 
            KEY_FILE_BLOB}, null, null, null ,null, null);

}

// Delete the current PDF file from the database
public boolean deletePDFFile(long rowId){
    return this.mDataBase.delete(DATABASE_TABLE, KEY_ROW_ID +"=" + rowId, null) > 0;
}

// Close the Database connection
public void close(){
    if(mDbHelper != null){
        mDbHelper.close();
    }
}

}

看起来我上面的代码中有个bug。在使用数据库中的字节数组编写新文件之前,我调用了
flush()
,从数据库中的blob创建.pdf文件时,这会导致一个空指针。如果您有兴趣学习如何将文件作为字节数组从资产复制到数据库,并将其存储为blob,我将我的解决方案发布在第一个主活动类下面,以及如何从数据库中读取字节数组,并在创建新文件并使用该文件名创建Uri后将其传递给新活动。

为什么要先将资源复制到blob,然后再复制回来?为什么不直接打开资源(如果你的应用程序的PDF查看器是本地的)、复制资源(如果不是),或者最好为PDF文件提供一个内容提供商?好问题。这是一个模拟在设备上从sqlite db打开pdf的演示。当我正确理解这一部分时,我将添加从Web服务下载多个PDF的功能,然后在从列表中选择它们时打开它们。这有意义吗?或者有更好的方法吗?粗略地看一下,您的代码似乎还可以。但是,您没有包括
PDFDbAdapter
,因此可能有东西坏了。在生产代码中,我仍然建议使用内容提供商,而不是将文件复制到外部存储。同意,我将提供上面的另一个类,以便您可以查看。谢谢。我解决了我的问题。代码中有一个bug。当我试图从数据库检索字节数组时,我得到了一个空指针异常。