2017-09-09 20 views
1

私はFirefoxのアドオンSDK拡張WebExtensionsに移植しています。以前はブラウザの検索エンジンにアクセスできましたが、今はできません。有用なユーザーが、すべてのエンジンがインストールされているsearch.json.mozlz4ファイルを読むように勧めました。しかし、このファイルはLZ4圧縮のjsonであり、Mozillaのown LZ4 formatにはカスタムのマジックナンバー「mozLz40 \ 0」があります。(JavaScriptのは、Firefox)WebExtensionsにLZ4圧縮されたテキストファイル(mozlz4を)読ん

、1はmozlz4ファイルを含め、LZ4圧縮を使用して、テキストファイルを読むためにこれを使用することができる前に:

let bytes = OS.File.read(path, { compression: "lz4" }); 
let content = new TextDecoder().decode(bytes); 

は(私はそれが動作する、「圧縮」フィールドについてのドキュメントを見つけることができませんでしたが)

は今、WebExtensionsを使用して、私はファイルを読むために思い付くことができる最高のは、これはどのような方法で圧縮処理されません

var reader = new FileReader(); 
reader.readAsText(file); 
reader.onload = function(ev) { 
    let content = ev.target.result; 
}; 

です。 This libraryはLZ4 を処理しますが、node.js用ですので使用できません。 [編集:それもスタンドアロンで動作します]。

import lz4 
file_obj = open("search.json.mozlz4", "rb") 
if file_obj.read(8) != b"mozLz40\0": 
    raise InvalidHeader("Invalid magic number") 
print(lz4.block.decompress(file_obj.read())) 

がどのように私は、これはJSで行うことができます。このPythonコード、比較して、期待通りに動作しながら、しかし、私はカスタムのマジックナンバーの処理を削除した場合でも、私は、それがファイルを解凍するために得ることができませんか?

+0

ありがたいことに、私が間違っていたとノードLZ4は、実際にラッパーを避けるために、 'require'を実装するだけでなく、スタンドアロンで動作します。しかし、それはカスタムlz4マジックナンバーを持つ特定のmozlz4フォーマットを処理しているようには見えません(データとそれぞれのチェックからマジックナンバーを取り除いても)。私はこのすべてで質問を更新しました。 – CanisLupus

答えて

2

多くの試行錯誤の後、私は最終的にWebExtensionにsearch.json.mozlz4ファイルを読み込んでデコードすることができました。 uncompress(外部アクセス用decodeBlockとしてエイリアス) - - あなたは一つの機能のみを必要とするでしょうけれどもあなたは、node-lz4 libraryを使用することができますので、私はdecodeLz4Blockにそれを名前を変更し、わずかな変更でそれをここに含ま:

// This method's code was taken from node-lz4 by Pierre Curto. MIT license. 
// CHANGES: Added ; to all lines. Reformated one-liners. Removed n = eIdx. Fixed eIdx skipping end bytes if sIdx != 0. 
function decodeLz4Block(input, output, sIdx, eIdx) 
{ 
    sIdx = sIdx || 0; 
    eIdx = eIdx || input.length; 

    // Process each sequence in the incoming data 
    for (var i = sIdx, j = 0; i < eIdx;) 
    { 
     var token = input[i++]; 

     // Literals 
     var literals_length = (token >> 4); 
     if (literals_length > 0) { 
      // length of literals 
      var l = literals_length + 240; 
      while (l === 255) { 
       l = input[i++]; 
       literals_length += l; 
      } 

      // Copy the literals 
      var end = i + literals_length; 
      while (i < end) { 
       output[j++] = input[i++]; 
      } 

      // End of buffer? 
      if (i === eIdx) { 
       return j; 
      } 
     } 

     // Match copy 
     // 2 bytes offset (little endian) 
     var offset = input[i++] | (input[i++] << 8); 

     // 0 is an invalid offset value 
     if (offset === 0 || offset > j) { 
      return -(i-2); 
     } 

     // length of match copy 
     var match_length = (token & 0xf); 
     var l = match_length + 240; 
     while (l === 255) { 
      l = input[i++]; 
      match_length += l; 
     } 

     // Copy the match 
     var pos = j - offset; // position of the match copy in the current output 
     var end = j + match_length + 4; // minmatch = 4 
     while (j < end) { 
      output[j++] = output[pos++]; 
     } 
    } 

    return j; 
} 

そして、この関数を宣言しますそれは、Fileオブジェクト(パスではなく)を受信し、成功/エラーのためコールバック:

function readMozlz4File(file, onRead, onError) 
{ 
    let reader = new FileReader(); 

    reader.onload = function() { 
     let input = new Uint8Array(reader.result); 
     let output; 
     let uncompressedSize = input.length*3; // size estimate for uncompressed data! 

     // Decode whole file. 
     do { 
      output = new Uint8Array(uncompressedSize); 
      uncompressedSize = decodeLz4Block(input, output, 8+4); // skip 8 byte magic number + 4 byte data size field 
      // if there's more data than our output estimate, create a bigger output array and retry (at most one retry) 
     } while (uncompressedSize > output.length); 

     output = output.slice(0, uncompressedSize); // remove excess bytes 

     let decodedText = new TextDecoder().decode(output); 
     onRead(decodedText); 
    }; 

    if (onError) { 
     reader.onerror = onError; 
    } 

    reader.readAsArrayBuffer(file); // read as bytes 
}; 

次に、あなたのアドオンのユーザーの検索と選択search.json.mozlz4をすることができます設定ページにHTMLボタンを追加することができます(WebExtensionsでは、ユーザの介入なしにファイルシステム内のファイルを単に開くことはできません) :

<input name="selectMozlz4FileButton" type="file" accept=".json.mozlz4"> 

(ここで私はエラーコールバックを使用していないが、することができます)私たちは、以前に宣言されたメソッドを呼び出す、このようなものを使用して、ファイルを選択し、ユーザーに応答する:

let button = document.getElementsByName("selectMozlz4FileButton")[0]; 
button.onchange = function onButtonPress(ev) { 
    let file = ev.target.files[0]; 
    readMozlz4File(file, function(text){ 
     console.log(text); 
    }); 
}; 

私はこれが誰かを助けることを願っています。私は確かに、この単純なことをするのに多くの時間を費やしました。 :)

関連する問題