Android sqlite如何检索blob> 1 mb正确地成块 [英] Android sqlite how to retrieve blob > 1 mb in chunks correctly

查看:174
本文介绍了Android sqlite如何检索blob> 1 mb正确地成块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题是,仅使用Google Pdf Viewer打开保存的文件,而pdf文件中的部分内容不清楚,而Adobe Acrobat根本无法打开该文件,因为该文件已损坏.创建的文件肯定存在问题,但我看不到.

My problem is that the file saved is only opened with Google Pdf viewer and the pdf file has parts that are unclear, and adobe acrobat isn't opening it at all because the file is damaged. There is certainly a problem with the file created but I don't see it.

现在是上下文: 我使用dbflow处理与服务器的sqlite db同步.保存时没有错误,如果我将文件直接保存到下载"目录,则可以正常查看文件.这些Blob保存在一个只有ID和Blob的新表中,并按如下所示的块进行检索:

And now the context: I use dbflow to handle sqlite db synchronization with the server. At the point of saving there is no error, and if I save the file directly to Downloads directory the file is being viewed okay. The blobs are saved in a new table that only has the id and the blob, and is retrieved in chunks like this:

  DatabaseDefinition database = FlowManager.getDatabase(Database.NAME);
        AndroidDatabase android = (AndroidDatabase) database.getWritableDatabase();
        Cursor rawQuery = android.rawQuery("select length(blob) from table where id=" + String.valueOf(id), null);
        int blobLength = 0;
        if (rawQuery != null) {
            while (rawQuery.moveToNext()) {
                blobLength = rawQuery.getInt(0);
            }
            rawQuery.close();
        }

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );

        final int CHUNK_SIZE = 1024 * 4;

        loop:
        for(int i = 0; i< blobLength/CHUNK_SIZE + 1; i++) {
            int ceiling =  (i+1)*CHUNK_SIZE > blobLength ? blobLength : (i+1) *CHUNK_SIZE;
            Cursor readBlobChunk =  android.rawQuery("select substr(blob, " +  i*CHUNK_SIZE + 1 + "," + ceiling + ") from table where id =" + String.valueOf(id), null);

            try {
                if (readBlobChunk != null) {
                    readBlobChunk.moveToFirst();
                    outputStream.write(readBlobChunk.getBlob(0));
                }
            } catch(ArrayIndexOutOfBoundsException e ) {
                Log.e(TAG, "blob chunk read exception", e);
                break loop;
            } catch (IOException e) {
                Log.e(TAG, "blob chunk io exception", e);
            }
            readBlobChunk.close();
        }
        byte[] picture = outputStream.toByteArray();
        try {
            outputStream.flush();
            outputStream.close();
        } catch (IOException e) {
            Log.e(TAG, " io exception", e);
        }

        //save file from bytearray to download directory
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(advResource,false);
            out.write(picture);
            out.flush();
            out.close();
        } catch (FileNotFoundException e) {
            Log.e(TAG, "exception", e);
        }  catch (IOException e) {
            Log.e(TAG, "exception", e);
        }

我说过,根据块大小,文件看起来可能好坏.

I remarked that depending on chunk size the file can look better or worse.

推荐答案

您想一次读取CHUNK_SIZE个字节. 虽然偏移量是正确的,但赋予substr()的长度随每个块而增加:

You want to read CHUNK_SIZE bytes at a time. While the offset is correct, the length given to substr() increases with each chunk:

        int ceiling =  (i+1)*CHUNK_SIZE > blobLength ? blobLength : (i+1) *CHUNK_SIZE;
        Cursor readBlobChunk =  android.rawQuery("select substr(Picture, " +  i*CHUNK_SIZE + 1 + "," + ceiling + ") from table where id =" + String.valueOf(id), null);

如果跟踪剩余字节,逻辑将变得更简单:

The logic becomes simpler if you track the remaining bytes:

remaining = blobLength;
while (remaining > 0) {
    int chunk_size = remaining > CHUNK_SIZE ? CHUNK_SIZE : remaining;
    query("SELECT substr(Picture, "+ (i*CHUNK_SIZE+1) + ", " + chunk_size + "...");
    ...
    remaining -= chunk_size:
}

这篇关于Android sqlite如何检索blob&gt; 1 mb正确地成块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆