質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

4回答

520閲覧

ビットデーターを効率良く保存する方法とは

xmg

総合スコア20

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2020/10/03 04:07

編集2020/10/03 10:09

おたずねいたします。
以下のような、長さがバラバラなデーターを
javascript でひとつにまとめて書き出す方法を検討しています。

data

1sample data 2 3data(0) = 4d 54 4data(1) = 68 64 00 5data(2) = e0 4d 54 72 6b 00 00 15 6data(3) = d4 00 ff 03 00 00 7data(4) = ff 02 12 43 8data(5) = 6f 70 79 72 69 67 9data(6) = 68 74 10data(7) = 20 28 11data(8) = 43 29 20 32 30 32 12data(9) = 30 00 ff 13data(10) = 58 04 01 03 18 14 15. . . 16. . . 17. . . 18

とりあえず、すべてのデーターを
たった一つの文字列変数に次々と書き足す方法で
コードを作成するところまで行き着きました。

その後、色々な見本を調べて回って
Uint8Array などの方法が使えるかもしれないところまで
情報を集めました。

上述のデーターの例ですと、Uint8Array の配列要素のひとつずつの容量を
超過してしまうのかどうか、など
基本的なことがどこにも書いてありません。

質問の目的

上述のビットデーターを最終的に1つの巨大データとしてつなげて
バイナリーコードとして javascript で
ひとつのファイルに書き出す方法を求めています。

よろしくお願いいたします。

これまで実行した方法

for loop を使って
文字列変数に 上記のビットデーターを
膨大な長さの文字列に書き加え続ける方法

for ( i=0; i< data.length; i++ )
str = str + data(i) ;

この方法では、ブラウザ上で実行すると
ものすごく処理速度が遅く
上に見本を示したようなわずか10個ほどのテストデーターより
はるかに大量の情報を処理する際に
メモリー容量を超過する恐れを懸念しています。

求めている解決法

ブラウザ上で、200個から500個程度の入力データーを
16進数に変換して読み込んで、そのうち
設定条件に合うものだけを関数処理して
計算結果が上のようなビットデーターとして得られます。

これらのビットデーターを上から順に空白文字を入れないで
javascript 上 (node.js の使用法を知りません)で
ひとかたまりに結合して
バイナリファイル形式で保存する方法を作ろうとしています。

Uint8Array などの使用方法が分からないため
どのようにコードを構築すればよいかご指導をお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

think49

2020/10/03 04:12

改行に意味はあるのですか。改行は復元対象ですか。
think49

2020/10/03 04:19

それと質問内容が不明です。 「これまで実行した方法」で出来たのでしょうか。 できたなら何が問題だったのでしょう?
Zuishin

2020/10/03 08:49 編集

どこまで聞いているのかよくわかりませんが、回答者たちはデータ圧縮前提で回答しています。圧縮が必要でしょうか? また実行環境はブラウザでしょうか? それとも node.js でしょうか? 素直に読むなら、データの保持は ArrayBuffer が良いと思います。 https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer これを文字列に変換する、または文字列から ArrayBuffer に戻すには BASE64 が簡単です。 https://developer.mozilla.org/ja/docs/Web/API/WindowBase64/Base64_encoding_and_decoding ファイルを扱うには File API が使えそうです。 https://developer.mozilla.org/ja/docs/Web/API/File/Using_files_from_web_applications リテラルからデータを作成するには、Uint8Array が使えますね。これは背後で ArrayBuffer を使用します。 https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array
Zuishin

2020/10/03 10:27 編集

> 計算結果が上のようなビットデーターとして得られます。 ここまではできているということですか? それとも > ブラウザ上で、200個から500個程度の入力データーを > 16進数に変換して読み込んで ここからまだですか? また、データはどこから得られますか? スクリプトの中に直書きするということですか? なぜこれを聞くかというと、 > data(0) = 4d 54 これは文法エラーになります。つまり、データがどのような形で変数に入っているかわからないため、その先へ進めません。
AkitoshiManabe

2020/10/03 16:44

> 入力データーを16進数に変換して読み込んで、そのうち設定条件に合うものだけを関数処理 これが速度的なネックになっていそうです。 処理方法をコードで示すことはできますか?
guest

回答4

0

ベストアンサー

上述のビットデーターを最終的に1つの巨大データとしてつなげ

「ビットデーター」をバイト配列と捉えるなら、ArrayBuffer を用いて結合する例も参考になるかもしれません。

javascript

1let 2 datalist = [ 3 new Uint8Array([0x4d, 0x54]), 4 new Uint8Array([0x68, 0x64, 0x00]), 5 new Uint8Array([0xe0, 0x4d, 0x54, 0x72, 0x6b, 0x00, 0x00, 0x15]), 6 new Uint8Array([0xd4, 0x00, 0xff, 0x03, 0x00, 0x00]), 7 new Uint8Array([0xff, 0x02, 0x12, 0x43]), 8 new Uint8Array([0x6f, 0x70, 0x79, 0x72, 0x69, 0x67]), 9 new Uint8Array([0x68, 0x74]), 10 new Uint8Array([0x20, 0x28]), 11 new Uint8Array([0x43, 0x29, 0x20, 0x32, 0x30, 0x32]), 12 new Uint8Array([0x30, 0x00, 0xff]), 13 new Uint8Array([0x58, 0x04, 0x01, 0x03, 0x18]) 14 ], 15 16 totalLength = datalist.reduce( (acc,byt) => acc + byt.byteLength, 0 ), 17 ab = new ArrayBuffer( totalLength ), 18 dv = new DataView(ab), 19 pt = 0 20; 21 22datalist.forEach( byt => { 23 for (let i=0,l=byt.byteLength; i<l; i++, pt++) { 24 dv.setUint8( pt, byt[i] ); 25 } 26}); 27console.log( dv.buffer ); 28// => ArrayBuffer(47) {}

バイナリダンプして、正しく結合できたかを確認します

javascript

1const dump = ( buf ) => { 2 let 3 len = buf.byteLength, // ArrayBuffer からバイト長を求める 4 u = new Uint8Array( buf ), // TypedArray を介して ArrayBuffer を操作 5 dump = [], tmp 6 ; 7 for( let i=0; i<len; ++i ) { 8 if( i % 16 === 0 ) dump.push( tmp=[] ); 9 tmp.push( u[i].toString(16).padStart(2,"0") ); 10 } 11 return dump.map( l=>l.join(" ") ).join("\n"); 12}; 13 14console.log( dump(dv.buffer) ); 15/* 16 => 4d 54 68 64 00 e0 4d 54 72 6b 00 00 15 d4 00 ff 17 03 00 00 ff 02 12 43 6f 70 79 72 69 67 68 74 20 18 28 43 29 20 32 30 32 30 00 ff 58 04 01 03 18 19 */

復元が必要なら、複合用の冗長なデータを持たせる必要があります。
PNG ファイルがチャンクという単位を持たせ、復元可能な内容にしています。

投稿2020/10/03 06:15

編集2020/10/03 06:30
AkitoshiManabe

総合スコア5434

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

xmg

2020/10/14 11:20

初学者にとって極めて難解な問題を分かりやすくご解説いただき、ありがとうございました。 深くお礼を申し上げます。
guest

0

昔よくあった方法ですが
保存は
バイト配列をRGBA変換して<canvas>タグに描写
あとは画像として保存(RGBAで情報が残るなら形式は何でも)。
サイズが可変の場合最初か最後のピクセルのRGBA(4バイト)に書きこんでおく

読込は
画像を<canvas>タグに読み込んで1ピクセル単位に読み込むだけ

※PGBAでなくPGBでも可

投稿2020/10/03 04:47

編集2020/10/03 05:09
kuma_kuma_

総合スコア2506

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

AkitoshiManabe

2020/10/03 06:17

A値に 0,255以外の値を書き込むと ピクセルは半透明を表現するために合成されて RGB のデータが壊れます。RGB(3バイト)に書き込むのが正しい回答と思います。
kuma_kuma_

2020/10/03 06:39 編集

> RGBAで情報が残るなら形式は何でも >※PGBAでなくPGBでも可 だからわざわざ上記の様に注意書きで書いているのですが? 3バイト配列(RGB)だと数値型に変換する時に都合が悪いので4バイト配列(PGBA)を 先に書きましたが保存方法によってはRGBAで残らないのでその場合PGBとして下さい。 ここまで書かないと理解できない?
AkitoshiManabe

2020/10/03 06:46

> ここまで書かないと伝わらない? 申し訳ありません。追記されていたのですね(リロードせずに投稿していました)。
guest

0

いろいろ方法はあると思いますが、
結局あなたの思ってるように、文字列で格納してくいのがいいかとおもいますよ。

んで、バイト間のスペースは削除して、

4d54 686400 e04d54726b000015 ...

でいいんじゃないでしょうか

投稿2020/10/03 05:09

y_waiwai

総合スコア88042

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

基数変換

圧縮だけなら、基数変換という原始的な方法もあります。

  • Number.prototype.toString で36進数に基数変換する
  • String.fromCharCode() で255進数に基数変換する

sample dataで

plain

1e0 4d 54 72 6b 00 00 15

この1行を一つの数字と見なせば、圧縮率は更に上がります。
改行に意味がないなら、全行を一つの数字と見なしてもよいかもしれません。

圧縮ライブラリ

zipの圧縮ライブラリを使えば、一つの書庫になります。
「zip + 基数変換」の重ねがけもよいかもしれません。

Re: xmg さん

投稿2020/10/03 05:07

think49

総合スコア18189

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問