バイナリデータの書込みについて

このQ&Aのポイント
  • バイナリデータの操作において、ビッグエンディアンのshortやlongのデータを書き込む際にデータが壊れてしまう問題について質問します。
  • データ長を指定せずにpackしてデータを書き込むという方法は成功しているが、これからのデータ加工に不安を感じています。
  • 質問の意図が理解できず困っており、質問内容に不足があれば補足することも可能です。
回答を見る
  • ベストアンサー

バイナリデータの書込みについて

こんにちは、初めまして。 さっそくなんですが、バイナリデータの操作を行っていて、ちょっと気になることがあり、質問させて頂きます。 現在あるバイナリデータファイルの読出しには成功し、一応思った通りに書込み、 そのデータは壊れず、読み出せたんですが・・・。 そのバイナリデータファイルは当然のように、アスキー型や文字型、ビッグエンディアンのshortやlongがバイト長ごとに入り混じってます。 アスキー型や文字型は問題なく読み書きできるんですが、 ビッグエンディアンのshortやlongを書き込む時、バイト長を指定してやると、データが壊れてしまいます。 例えば、2バイトのビッグエンディアンのshortを読み出して、そのままリスト値に変換をかけ、なにも加工することなく、再びバイナリ構造体に変換しても、データが壊れてしまいます。 例 失敗) INは読み出すファイル、OUTは書き込むファイル read (IN,$dataB,2); $dataA = unpack("n2",$dataB); $dataB2 = pack("n2",$dataA); print OUT $dataB2; 現在、packするときに、データ長をしてせず、*とすることでデータの書込みには成功してる(ちゃんと読めるデータとして)んですが、これから先、こういったデータを加工して書き込む場合、データ長を指定せずに書き込むというのは・・・。ちょっと嫌な感じです。 例 成功) INは読み出すファイル、OUTは書き込むファイル read (IN,$dataB,2); $dataA = unpack("n2",$dataB); $dataB2 = pack("n*",$dataA); print OUT $dataB2; 何が原因なのか、わからず困っています。 なにぶん素人なもので、やってること自体間違っているのかもしれませんが、どなたか御回答頂ければ幸いです。 ここに書いている質問の意図がわからない等、ありましたらその旨お答え頂ければ、私の知る限りお答えしようと思いますので、どうか宜しくお願い致します。

  • Perl
  • 回答数1
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

readの3番目の引数は読みこむバイト数を指定しますが、shortは 2byteですから、2 * 2で4byteを読みこむ必要があります。 それから、unpackを $data = unpack(...) の形で受け取るとこれはスカラーコンテクストになりますから、 展開された値の最初の要素だけが$dataに返されます。 @data = unpack(...) のように配列で受け取れば、リストコンテクストになり、展開された 値すべてが@dataに格納されます。 よって、以下のようにすればお望みの結果が得られるのではないで しょうか。 read (IN,$dataB,4); @dataA = unpack("n2",$dataB); $dataB2 = pack("n2",@dataA); print OUT $dataB2; ひょっとしたら、OUTはINと同じファイル、もしくはそれをコピーした ものなのではありませんか? だとしたら、「pack("n*", $dataA) にすると成功する」というのは、n2だと $dataAと空(すなわち0)の二つのshort値が書きこまれる(0で上書きされる 部分がある)のに対し、n*だと$dataAだけをpackした一つのshort値が書き こまれるので、0で上書きされる個所がない、ということなんだと類推されます。 あるいは実際はもっと複雑なpackを行っていて、他の要素との兼ね合い があるのかもしれませんが。

hayate_p
質問者

お礼

お返事遅れてすみませんでした。 全てHead_Syndicateさんのおっしゃる通りで、ばっちりうまくいきました。 ひょっとしたら・・・以下もまさにその通りでした。 本当にありがとうございます。 また、この場にて、質問させて頂く機会があるとは思いますが、そのときはよろしくお願いします。 本当に助かりました。ありがとうございました。

関連するQ&A

  • C++でバイナリデータの扱い方

    以下のプログラムで接続先からバイナリデータを取得しているのですが coutで出力しても画面に何も表示されません。 ------------------------------------------------------ /*include部分は省きます*/ std::string bin; //1 clx::http session(clx::uri::encode(ip), 80); //2 session.get(clx::uri::encode(param)); //3 bin = session.body(); //4 std::cout << bin << std::endl; //5 ------------------------------------------------------ 上記プログラムを空ファイルにリダイレクトしバイナリエディタで見たら ちゃんとデータは書き込まれていました。 5行目を以下のように変えても空欄が出力されただけで文字は表示されませんでした std::cout << std::hex << bin << std::endl; しかし以下のようにすると文字数は表示されました。 std::cout << bin.length() << std::endl; やりたいこととしてはphpのpack()、unpack()的な部分です。 例えば 値をフォーマットを指定してバイナリデータとして出力 $val=pack("L", 35); とか バイナリデータを変数から指定バイト分取り出して10進数で画面に出力 $bin=(バイナリデータ); $val=unpack("c",$bin); echo(sprintf("%d",$val)); です。 バイナリの扱いはリトルエンディアンです。 ご教示お願いしますm(__)m

  • バイナリデータからの値の取得について教えてください

    今、バイナリデータから値を取りだそうとがんばっています。 しかし、うまくいかずに困っています。 困っていることは2点あります。 (1)バイナリデータにはリトルエンディアンで格納していると書いています。 まず、リトルエンディアンで書かれている場合、どのような処理を考えることが必要なのでしょうか? (2)バイナリデータには、 はじめに文字列(char)型4バイトで「RIFF]という値 次に32ビット符号なし整数で4バイトの数字、 次に4052バイトの構造体 などと収納されているようです。 このように入っているデータから値を取得するにはどのようにしたらよいのでしょうか? 全然できなくて困っています。 教えていただけないでしょうか? よろしくお願いいたします。

  • ruby バイナリ入出力について

    ruby初心者です。 バイナリファイルを読み込んで、その値を2倍して再びバイナリファイルに書き込む ソースを作りたいのですが、どなたかご教示願えますでしょうか。 以下試行錯誤して作ってみたのですが、このソースだと 例えば31というバイナリデータが62で書かれず、 36、32のasciiコードで保存されてしまいます。。 ----------------------------- BinData = open("in.data") BinData.binmode File.open("out.data", "wb"){|f| while (b = BinData.read(1)) m = b.unpack('C')[0]*2     #取り込んだバイナリデータを整数化して2倍 p sprintf("%x", m) k = format("%x", m)       #16進数に変換 f.write(k) end } すみませんが宜しくお願い致します。

  • バイナリファイルの計算方法

    バイナリデータをはじめて扱う初心者です。 バイナリデータファイルからデータを読み出したいと思います。 環境はWindowsXPとLabView7.1です。 バイナリエディタで見てみると、  E8 03 と格納されている、2バイトshort型のデータがあります。 LabView7.1を使って、E8 03 という配列要素を読み出すことまではできました。 次に、この値を10進数で表現すると、いくつになれば正解なのでしょうか? (E8 03 という値をどのように計算して10進数にすればいいのでしょうか?) 私なりにプログラムした結果、-24か232のどちらかだと思うのですが自信がありません。 (データ自体が計測器が吐き出したデータなので、どのような値が入っているかわからないのです。 LabViewがビックエンディアンを使っていることも、正解に自信が持てない一因です) バイナリエディタで10進数に変換してくれるようなツールがあれば一番いいのですが。 ご存知の方がいらっしゃいましたら、ご教授ください。

  • 統計の問題

    統計学の問題を解いていただきたいです。今までスマホを使って解いていましたが、故障したため、できない状態です。パソコンはありません。 この質問は友達に投稿してもらっています。 dataA = c(18.3, 16.9, 18.1, 17.7, 17.9, 17.3, 18.7, 18.3, 16.3, 15.0, 17.9, 18.2, 15.3, 18.5, 16.9, 18.4, 17.4, 17.9, 17.8, 16.3, 17.4, 17.2, 16.7, 17.4, 17.7, 15.5, 17.3, 16.3, 15.1, 16.4) dataB = c(17.8, 19.1, 18.6, 17.6, 18.7, 19.2, 15.9, 18.9, 19.1, 18.7, 13.1, 16.2, 16.8, 18.5, 18.0, 17.5, 18.4, 16.1, 18.1, 16.3, 16.5, 17.2, 18.2, 15.9, 16.0, 17.7, 18.7, 18.8, 18.2, 18.6) ① それぞれのデータにおける「平均値(算術平均)」,「自由度」,「不偏分散」を求めよ. 平均値 mean(dataA) mean(dataB) 自由度 length(dataA)-1 length(dataB)-1 計算式で出した不偏分散 sum((dataA -mean(dataA))^2)/(length(dataA)-1) sum((dataB -mean(dataB))^2)/(length(dataB)-1) ② それぞれのデータにおける「標準誤差」および「95%信頼区間」を求めよ. 標準誤差 標準偏差 / sqrt(n) sqrt(var(dataA)) / sqrt(length(dataA)) sqrt(var(dataB)) / sqrt(length(dataB)) 95%信頼区間 mean(dataA)+(qnorm(0.95) * sd(dataA)) mean(dataA)-(qnorm(0.95) * sd(dataA)) mean(dataB)+(qnorm(0.95) * sd(dataB)) mean(dataB)-(qnorm(0.95) * sd(dataB)) ③ それぞれのデータを平均0,標準偏差1のデータにZ変換せよ. ④ 5%水準において,dataAとdataBの平均値に差があるかどうか判定せよ.なお,回答には対立仮説および帰無仮説を明記すること.また「入力したコマンド」や「出力結果」を示すとともに,「判定するために読み取った場所」および「なぜそのように判定したのか」を説明すること. t.test(x=dataA,y=dataB,conf.level=0.95,var.equal=F)

  • エンディアン:2バイトのデータをShort intにしたいのですが?

    1.Intelの CPU リトルエンディアンでの、問題です。 バイナリファイルをバイト単位で読込み、これを16ビットの整数にしたいのですが、以下のようにコーディングしましたが、うまくいきません。解決方法をご教示下さい。 char s[2]; short int x;   // 16ビットの整数です // s[0] s[1]に、データを読み込みます。 x = (short)(s[0] + 256 * s[1]); 2.同様の問題で、ビッグエンディアンの場合は、どうすればよいかも、ご教示下さい。 よろしくお願いします。

  • MIMEとバイナリデータの読み方

    バイナリファイルの中、MIME boundary1の後、ヘッダーの部分のXMLで書かれたテキストファイルあります。そのXMLヘッダー文をパースしたい。 バイナリファイルのほかのところにMIME boundary2の後バイナリ形式のデータあります。 Googleで調べたけど、なにかは見つかったけど、理解できず困っています。 バイナリファイルを一バイトづつ読んで、Integer.toHexString()を使うとASCIIの形でXMLの部分はそのまま (フォーマットなしで)、バイナリデータの分は化けた表示されます。 だいたいのアウトラインでよいです。やり方ご存知の方、教えてください。 (1)boundary1の後書かれたXML式データを読む方法 (2)boundary2の後、決まったキーワードが入っていたら、そこから決まったバイト数までのバイナリデータを読む方法 その決まったキーワードと決まったバイト数はヘッダーのXML内に書かれています。

    • ベストアンサー
    • Java
  • 差分バックアップだと二世代前のデータは消えますか?

    I-O DATAの外付けハードディスクを使用しています。 EasySaver3.1 LE というI-O DATAの無料ソフトを使って 前回フルバックアップをし、今回は差分バックアップを取ろうと思っています。 そこで質問ですが、差分バックアップだと二世代前のデータは消えますか? 有料ソフトだと履歴機能がありますがこの無料ソフトだと無い、と書いてありました (この履歴機能というのが何なのかよく分かってないです)。 この無料ソフトだと一世代前のデータしか残らないのですか? 例を挙げると、元々 DataA DataB DataC という三つのファイルがあってフルバックアップしたとします(一世代目)。 そして、DataAだけ消します。 DataB DataC この二つのファイルの状態で差分バックアップをします(二世代目)。 そして、今度はDataBを消します。 DataC このDataCだけの状態で差分バックアップをします(三世代目)。 ここで「DataAがやっぱり必要だった!」となった場合、DataAを復元できますか? 他のメーカ/機種での一般的な話でも構いません。 どうか教えて下さい。お願いします。

  • バイナリファイルとバイナリ文字列の違い

    がわかりません。 例えば >http://e-words.jp/w/E38390E382A4E3838AE383AAE58897.html をみるとバイナリ列は1バイトを連ねたものだというらしいです。 つまり【文】という文字列を文字コードUTF-8でバイト配列化すると [1] => 230 [2] => 150 [3] => 135 となります。 (これはPHPでunpackかけましたが他の言語のGetBytes()などでも同じバイト値がでました。) この【文】という文字列はバイナリ列になるわけですよね? 例えばこの【文】という文字だけを保存したbun.txtというファイルはバイナリーファイルに なるのでしょうか? バイナリファイルの定義をみると >http://e-words.jp/w/E38390E382A4E3838AE383AAE38395E382A1E382A4E383AB.html 上記URLだと >文字コードの範囲などを考慮せずに作成されたファイル というのがバイナリファイルであるとあります。 つまりバイナリファイルとは 1バイト・・つまり8ビット(0~255)までの数値で表したものを連ねたもので なおかつ、文字コードなどの解釈を一切行わなずに、バイト値のみが記述されたデータと おもってもよいのでしょうか?

  • バイナリ出力

    バイナリのテストデータを作成しており、VBAで作成中です。 以下の内容で困っております。 「0~65525の値を2バイトの情報(VCでいうunsigned shortの型)としてバイナリファイルに出力する。」 変数long型で値を取得した場合、4バイトの情報としてバイナリ出力されてしまいます。これを2バイトの情報として出力する方法をご教授願えないでしょうか? よろしくお願いします。

専門家に質問してみよう