【问题标题】:Trouble reading sqlite3 database columns of type blob with sql.js使用 sql.js 读取 blob 类型的 sqlite3 数据库列时遇到问题
【发布时间】:2014-07-08 09:46:57
【问题描述】:

所以我正在使用 sql.js 库,即 javascript 中的 sqlite 端口,可以在这里找到https://github.com/kripken/sql.js

这是我打开和读取来自本地平面文件存储的数据库的代码。

首先通过此 HTML 选择本地文件的文件

<input type="file" id="input" onchange="handleFiles(this.files)">

幕后js代码如下,

function handleFiles(files) {   
  var file = files[0]; 
  var reader = new FileReader();
  reader.readAsBinaryString(file);
  openDbOnFileLoad(reader); 
  function openDbOnFileLoad(reader){
    setTimeout(function () {
    if(reader.readyState == reader.DONE) {
      //console.log(reader.result);
      db = SQL.open(bin2Array(reader.result));
      execute("SELECT * FROM table");
    } else {
      //console.log("Waiting for loading...");
      openDbOnFileLoad(reader);
    }
    }, 500);    
  }
  
}

function execute(commands) {
  commands = commands.replace(/\n/g, '; ');
  try {
    var data = db.exec(commands);
    console.log(data);
  } catch(e) {
    console.log(e);
  }
}
function bin2Array(bin) {
  'use strict';
  var i, size = bin.length, ary = [];
  for (i = 0; i < size; i++) {
      ary.push(bin.charCodeAt(i) & 0xFF);
  }
  return ary;
}

现在这工作了,我可以访问数据库中的所有列和值,但是有一列是 blob 类型的,它只是显示为空。关于如何访问此 blob 内容的任何想法?

正确答案!

所以我在这个问题中想要问的只是如何使用 sql.js 读取 blob 类型的列的内容。正确答案是在问题中指定列名,对于包含 blob 类型数据的列,使用 hex 函数获取其内容,即从表中选择 column1,hex(column2)。这绝不是关于最有效的方法的问题。我还为此写了blog post

【问题讨论】:

    标签: sqlite blob javascript emscripten


    【解决方案1】:

    这是负责初始化我的 sqlite 数据库的函数的稍微修改的副本:

    sqlite.prototype._initQueryDb = function(file, callback) {
        self = this;
        var reader = new FileReader();
    
        // Fires when the file blob is done loading to memory.
        reader.onload = function(event) {
            var arrayBuffer = event.target.result,
                eightBitArray = new Uint8Array(arrayBuffer),
                database = SQL.open(eightBitArray);
            self._queryDb = database;
    
            // Trigger the callback to the calling function
            callback();
        }
    
        // Start reading the file blob.
        reader.readAsArrayBuffer(file);
    }
    

    在这种情况下,file 是我从 HTML 输入元素中获得的本地 sqlite 数据库句柄。我指定一个函数在该输入发生更改事件时调用,并从生成的 event.target.files[0] 对象中获取 blob。

    为了简洁起见,我遗漏了一些内容,但如果您仍在苦苦挣扎,我可以整理一个更小、更简化的示例。

    【讨论】:

    • 我已经工作的代码,我必须做的是指定我选择的列,并为 blob 列使用 Hex(column)。不过,我会试试这个解决方案,所以我有一个替代方案供将来参考。
    • 如果可能的话,我会欣赏一个更简单的例子吗?否则我会在我有时间的时候解决这个问题。我确实让我的代码工作了,我写了一篇关于这个captaindanko.blogspot.com.au/2014/05/…的帖子
    【解决方案2】:

    答案是:使用你上面提到的 kripken 的 sql.js,你不能。至少截至今天(2014 年 5 月)。 原作者不再维护sql.js

    但是,我是 sql.js 的一个分支的作者,可以在这里找到:https://github.com/lovasoa/sql.js

    此分支带来了多项改进,包括对预准备语句的支持,其中与原始版本相反,值在其自然 javascript 类型中处理,而不仅仅是作为字符串。

    在此版本中,您可以处理 BLOB(用于读取和写入),它们显示为 Uint8Arrays(例如,您可以将其转换为对象 URL 以显示内容给您的用户)。

    以下是如何从数据库中读取 blob 数据的示例:

    var db = new SQL.Database(eightBitArray); // eightBitArray can be an Uint8Array
    var stmt = db.prepare("SELECT blob_column FROM your_table");
    
    while (stmt.step()) { // Executed once for every row of result
      var my_blob = stmt.get()[0]; // Get the first column of result
      //my_blob is now an Uint8Array, do whatever you want with it
    }
    db.close(); // Free the memory used by the database
    

    您可以在此处查看完整文档:http://lovasoa.github.io/sql.js/documentation/

    【讨论】:

    • 因此 fork 的文档非常有用,但是您可以仅使用 sql.js 而不使用 fork 来读取 blob。我写了一篇博文,你可以看看,在这个链接上captaindanko.blogspot.com.au/2014/05/…
    • 我的fork也是sql.js。您的解决方案是一个很好的解决方法,但效率低下。 SQLite 首先必须将二进制数据转换为字符串。在内部,字符串存储在 ArrayBuffer(作为整数数组)中,是原始 BLOB 的两倍。然后,将其转换为 javascript 字符串(意味着必须再次读取和复制它),然后,您必须再次将其转换为二进制数据。当您使用我的 sql.js 版本时,不必执行这些转换,您可以直接从数据库中获取二进制数据。它只能以原始形式复制一次。
    • 您的效率可能是对的,但该解决方案并不是真正的解决方法,它只是证明您可以仅使用 sql.js 读取 blob 类型的列。
    • 这完全可以解决。您可以通过将 BLOB 转换为字符串并读取字符串来解决无法读取 BLOB 的问题。
    猜你喜欢
    • 2019-01-28
    • 2018-04-22
    • 1970-01-01
    • 2017-08-16
    • 2018-02-27
    • 1970-01-01
    • 2015-03-19
    • 2021-03-22
    • 2011-11-27
    相关资源
    最近更新 更多