NI製品ディスカッション

キャンセル
次の結果を表示 
次の代わりに検索 
もしかして: 

変調・復調の方法

解決済み
解決策を見る

「バイナリファイルから読み取る」及び「バイナリファイルに書き込む」関数と配列の関係について質問です。

 

あるファイルを対象に、「バイナリファイルを読み取る」関数で読み取ったデータを、

そのまま「バイナリファイルに書き込む」関数に入力すれば元のファイルが復元できますが、

読みとったデータを2回not演算する(変調、復調の最も単純な操作として採用しています)と、

データの中身は同じはずですが、復元できません。どうすれば復元できるでしょうか。

0 件の賞賛
メッセージ1/8
5,758件の閲覧回数

yama80様は、どのような実装をされているのでしょうか。

 

仮に、test.viのようなVIがあったとします。

「バイナリファイルから読み取る」関数で、データタイプとしてブールを指定していますので、input.txtから読み取ったデータは、一応ブール配列として返されることとなります。

しかしながら、このブール配列は、input.txtのバイナリ値を表しているわけではありません。

 

LabVIEWでは、ブールはサイズが1バイトのデータタイプとされています。

そして、「バイナリファイルから読み取る」関数から返されるのは、input.txtのサイズ (単位: バイト) と等しい個数のブール配列となりますが、実は、配列内の各ブール値の実体は、input.txtのデータに応じた0x00から0xFFのデータとなっています。

そして、実体データが0x00の場合のみ、ブール値はFALSEとなり、それ以外の場合はTRUEとして表現されます。

例えば、input.txt "ABC..." の場合、実体データは 0x41, 0x42, 0x43, ... となり、ブール値は TRUE, TRUE, TRUE, ...となります。

 

上記の様なブール値がNOTに入力されると、ブール値の実体が0x00でないものは0x00へ、0x00であるものは0x01に変換されます。

したがって、例えば、input.txt "ABC..." の場合、一度NOTへ入力されると、実体データは 0x00, 0x00, 0x00 となり、再度NOTへ入力されると、同じく 0x01, 0x01, 0x01, ... となります。

そして、ブール配列が「ブール配列に書き込む」へ入力されるとき、実際に書き込まれるデータは、各ブール値の実体に応じたものとなります。

したがって、上記の例の場合、output.txtに書き込まれるのは、0x01, 0x01, 0x01, ... に応じた文字列となり、結果、input.txtの内容が「復調」されないこととなります。

0 件の賞賛
メッセージ2/8
5,691件の閲覧回数
解決策
受理者 yama80

さて、それでは、どのようにすれば、input.txtのバイナリ値を1ビット単位で取得できるか、という議論が焦点になるかと思います。

そのためには、test2.viのように、「バイナリファイルから読み取る」関数で、データタイプとしてU8 (符号なし8ビット整数) を指定し、バイナリ値を1バイトずつ読み取った上で、それらを1ビット単位で参照できる様に変換することが有効です。

 

test2.viでは、U8でデータを読み取った後、「数値をブール配列に変換」VIを使用して、ひとつのU8の値を8個のブール値の配列に変換しています。

そして、変換後のブール配列に対してNOT演算を2度実施し、再度、U8へ変換し、output.txtに書き込んでいます。

 

上記のようにすれば、yama80様が仰る変調・復調の動作が実現できるかと考えられますが、いかがでしょうか。

0 件の賞賛
メッセージ3/8
5,688件の閲覧回数

ブールは8ビットで定義されているんですね.

丁寧なご説明に加え,サンプルプログラムの添付までしてくださって,

本当にありがとうございます.

お陰様で成功しました.

0 件の賞賛
メッセージ4/8
5,640件の閲覧回数

既に問題は解決されていると思いますが、ご参考まで、NOT関数はブールだけでなく、全ての整数型にも使えます。

U8の値をNOTに通せば、U8レベルで全ビットの反転が得られますので、ビット分解しなくても大丈夫と思います。

ご参考下さい。

0 件の賞賛
メッセージ5/8
5,626件の閲覧回数

ありがとうございます。

処理速度を上げる必要があるので助かりました。

0 件の賞賛
メッセージ6/8
5,623件の閲覧回数

なるほど、であれば、実際のデータ全体は、「U8の配列」の形になっていると思いますので、

U8の配列のままNOTに通す」ことで配列全体にNOTを施すこともできますし

(Forの中に書くより内部的には速い)、

あるいは、U8の配列を一度「U32の配列」に型キャストして、その配列にNOTを施すことで

内部的な繰り返し命令効率が僅かに上がるかも知れません。

(CPU命令的に、1バイトNOTをN回繰り返すのと、1ダブルワードNOTをN/4回繰り返すのと、

クロック的に後者の方が得なような気も。でもLabVIEWにも最適化はあるので、

配列演算を最も効率の良いやりかたに置き換えているかも知れません)

いずれにしても、ほとんどの数値・論理演算は配列のまま扱え、効率が良い場合もあるので、ご参考下さい。

0 件の賞賛
メッセージ7/8
5,621件の閲覧回数

勉強させていただきました。

詳細なところまでサポートして下さいましてありがとうございます。

0 件の賞賛
メッセージ8/8
5,619件の閲覧回数