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

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

新規登録して質問してみよう
ただいま回答率
85.46%
Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Q&A

解決済

2回答

4520閲覧

文字列形式で保存したバイナリデータを復元するには

you_19000

総合スコア31

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

0グッド

0クリップ

投稿2021/12/10 04:49

やりたい事

ローカルに保存しているPNGファイルを一旦テキスト形式に変換してテキストファイル内に保存
その後、使う際にテキストファイル内の上記データを取得して、PNGに戻したいです。

試した事

手探りで書いていますが、中々うまくいきません。

import fs from "fs"; const png = fs.readFileSync("sample.png"); const asciiPng = Buffer.from(new Uint8Array(png.buffer)).toString("ascii"); fs.writeFileSync("sample.txt", asciiPng);
const png = fs.readFileSync("sample.txt").toString(); const u8 = new Uint8Array(utf8Png); fs.writeFileSync("test.png", u8.buffer);

1つ目のコードはエラーはなく動作はします。
2つめのコードは以下エラーが発生します。

TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received an instance of ArrayBuffer at Object.writeFileSync (node:fs:2146:5) at file:///C:/app/png_chunk_sample/app.js:12:4 at ModuleJob.run (node:internal/modules/esm/module_job:183:25) at async Loader.import (node:internal/modules/esm/loader:178:24) at async Object.loadESM (node:internal/process/esm_loader:68:5) at async handleMainPromise (node:internal/modules/run_main:63:12) { code: 'ERR_INVALID_ARG_TYPE' }

これを回避してpngとして保存するにはどうするべきでしょうか
(また、そもそもこの方法でpngとして復元することは可能でしょうか)

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

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

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

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

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

int32_t

2021/12/10 05:44

なぜテキスト化したいのでしょうか? 他のテキストのデータと混在させたいのでしょうか?
guest

回答2

0

自己解決

以下で実現出来ました。

// encode const bin = fs.readFileSync("Sample.png"); const str = Buffer.from(bin).toString("hex"); fs.writeFileSync("sample.txt", str);
// decode const str = fs.readFileSync("sample.txt").toString(); const bin = Buffer.from(str, "hex"); fs.writeFileSync("test.png", bin);

投稿2021/12/10 14:39

you_19000

総合スコア31

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

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

0

https://shmztkyk.hatenablog.com/entry/2013/11/12/165457

utf8じゃなくてhexでとれってさ。

js

1var token = notification.device['token'] 2console.log(token.toString('hex', 0, token.length));

すると 3fa1327c1e25b58dc351c110d1b55a613168cd6b91a7b911e47ef88ce3XXXXXX みたいな文字列になってちゃんと取れました。

基本的にはこれで解決します。
Uint8Array等のArrayBuffer系はブラウザに積んであるJavaScriptの為にあります。
Node.jsにはBufferが用意されているので
どうしてもNode.jsとブラウザの両対応したいというケース以外では避けた方が良いですね。

上記を踏まえて質問文のソースコードに手を入れるとこんな感じになります。

js

1// encode 2import fs from "fs"; 3const bin = fs.readFileSync("sample.png"); 4const str = Buffer.from(png).toString("hex"); 5fs.writeFileSync("sample.txt", str);

js

1// decode 2import fs from "fs"; 3const str = fs.readFileSync("sample.txt"); 4const bin = Buffer.from(png, "hex"); 5fs.writeFileSync("test.png", bin);

Node.jsのBuffer.fromは色んな型を放り込んでよしなに動いてくれますが、
動かなかったらreadFileSync後に.toString()をかませて様子を見てください。

そもそもこの方法でpngとして復元することは可能でしょうか

仕様を考えれば十分いける範囲ですね
コンピュータは101010という二進数で動いているという話がありますが、
これだと区切りがわからなくて人間が死ぬので、
実際は1111の4桁を1文字に纏めた16進数で管理しています。

16進数の表現方法は普通の0-9にA-Fを追加した16文字を使います。
この16進数2桁の00-FFを1バイトと表現します
※因みに機械語の01の二進数1桁分を指して1ビットと呼ぶ

なので愚直にファイルの先端から読み取ったビット列をバイトの並びとして取り出して
0F1E2D3C...みたいな感じのテキストファイルに加工してやればシリアライズ(文字列化)は可能です。

逆にこのテキストファイルをビット列に変換しながら挿入していき、
1個のファイルに格納すればデシリアライズ(文字列からの復号)を行った事になります。

これが上で使ったhexのやっていることです。
latin1askii指定はバイナリ文字列を無理やりUTF-8への変換を挟む事になりそう。
編集前の回答も上手く動いて無かったので、多分不可逆になってデータが壊れてますね。

最後にお約束として記載しておきますが、
やってる事が意味があるか無意味かで言えばまぁほぼ無意味ですけどね。

投稿2021/12/10 05:13

編集2021/12/10 10:24
miyabi-sun

総合スコア21158

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

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

you_19000

2021/12/10 09:59

ご回答大変ありがとうございます! 早速試してみました。(latin1周りはもう少し勉強してみます) が、どうもWindows標準のビューワーで開くと ``` このファイルはサポートされていない形式です ``` と出てしまいました。 VSCodeで中身をテキスト形式で開くと頂いたコードのままだと変換前と変換後でencodingが変わってしまっていたので読取段階でlatin1に揃えてみたのですが、それでも開けませんでした。 ( ざっと中身を比較しても前後に余計なものが挿入されている感じはなく、pngのシグネチャもヘッダもきっちりいました) 手元で色々今試し続けているので見つけたら追記しつつ、もし何かヒントあれば頂けるとありがたいです... >> お約束として記載しておきますが、やってる事が意味があるか無意味かで言えばまぁほぼ無意味ですけどね。 はい。普通は意味がないのですが、社内のデータ保管先のルールの中でやりたいことをやろうとすると、この1回テキスト形式での保存がとてもやりたいのです... (ちゃんと脆弱性にならない範囲で勿論やる前提で)
miyabi-sun

2021/12/10 10:24

どれどれ……ちゃんと試さないで回答したらダメだわ?で試したら動きませんでした。 https://shmztkyk.hatenablog.com/entry/2013/11/12/165457 "hex"じゃねーか!騙された!! これを元に手元にあるPNGファイルに対して変換→再変換→ファイル保存を試みた所動いたので回答を書き直して置きます。
you_19000

2021/12/10 14:39

確認大変ありがとうございます! hexで良かったんですね。 ちなみに記載いただいた通りtoString()を嚙まさないと読み出しが失敗したので、最終的には以下のコードで実現出来ました。 大変助かりました!ありがとうございました。 (これでデータが保存できる...) // encode const bin = fs.readFileSync("Sample.png"); const str = Buffer.from(bin).toString("hex"); fs.writeFileSync("sample.txt", str); // decode const str = fs.readFileSync("sample.txt").toString(); const bin = Buffer.from(str, "hex"); fs.writeFileSync("test.png", bin);
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問