パソコン活用研究5番街(Visual Basic、Excel(VBA)、BASIC プログラミング研究)

Binary ファイルの入出力 書き込み

旧BASICにはなくて、VisualBasicで実装された機能の中で、使い込んでみると
かなり便利!という機能のひとつに
Binaryファイルの入出力Byte型変数(配列)があります。
Visual Basicの場合、文字コードの問題がからんできて、Binaryファイルの入出力とByte型変数
の理解を少々面倒なものにしていますが、十分に理解すればかなり便利な機能です。

1. Binaryモード

ファイルをBinaryモードとしてオープンするには以下のようにします。
Open filename For Binary As #n

Binaryモードでのファイルアクセス(入出力)とは、他のモード(シーケンシャルモードなど)と何が
違い、何が特徴なのでしょうか。まず、Binaryモードでのファイルアクセスについて簡単に記述して
みます。
Binaryモードとしてオープンすると、一般的に区切りの記号とされているカンマやCRコード(&H13)を
特別なコードとして扱わず、1バイト単位でファイルの先頭から逐次読み込み、書き出しをします。 
すなわち、Binaryモードとしてオープンすれば実行ファイルなどのBinaryファイルも読み込み、
書き出しができるようになるわけです。シーケンシャルモードでは、カンマやCRコードに相当する
値のデータ(&H21,&H13)をデータの区切り記号として認識するので、実行ファイルなどのBinaryファイル
を正しくアクセスすることはできません。

余談ですが、Binaryモードでのファイルの入出力はN88Basic,F-Basicといった旧BASICにはなかった
機能です。QuickBasicからは実装されています。
(旧Basicでも、別の方法でBinaryファイルの入出力はできたけれども)


2. Byte型変数

Byte型変数とは1Byteの領域をもった変数で、0〜255の値をとることができます。
Dim A() as byte
のように宣言します。

さて、VisualBasicの注意書きには、BinaryファイルのRead/Writeには文字列型変数ではなく、
Byte型配列を使うようにしなさいというお達しが書かれています。
旧Basicでの経験からすると、Binaryファイルの入出力に文字列型変数を使っても問題なさそうな
気がしますし、現にVisual Basicの一部の書籍では、Binaryファイルの入出力に、文字型変数を
使っても不具合はないというような記述もあります。
しかし、おじさんのプログラム経験ではやはり文字型変数では不具合が発生します。ここはMicrosoft
のお達しの通り、Byte型変数を使うのが良いでしょう。

文字列型変数ではうまくいかない最大の理由は、文字コードセットの問題です。
MS-DOS以来Windowsでも、文字コードとしてShift-Jisが一般に使われていますが、Visual Basic
は内部的にはUnicodeという文字コード体系を使っています。文字列型変数に読み込むと、
このコード変換が行われ、予期せぬことがおこるというのが、MicroSoftの説明です。詳しいことは
知る必要はないと思いますが、ともかく、Byte型を使えということです。


3. Binaryモードでの書き込み

では、試しに1〜255までのBinaryファイルを作って見ましょう。

Binaryモードでの書き込みには Put を使います。
書式は以下の通りです。
Put #n, [rec], var
Binaryファイルのrec位置に、変数varを書き込みます。

プログラム部分は以下のようです。


Dim a As Byte
Open "new1.dat" For Binary As #1    
For i = 1 To 255
a = i
Put #1, , a
Next
Close #1

変数 a はByte型として宣言されています
この結果できたnew1.dat というファイルをダンプしてみます。
1〜255(&H01〜&HFF)までのファイルができています。

-D
00 00 :01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 ................
00 10 :11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 ...............
00 20 :21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 !"#.%&'()*+,-./0
00 30 :31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 123456789:;<=>?@
00 40 :41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 ABCDEFGHIJKLMNOP
00 50 :51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60 QRSTUVWXYZ[\]^_`
00 60 :61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 abcdefghijklmnop
00 70 :71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F 80 qrstuvwxyz{|}~&127?
00 80 :81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F 90
cу・・葛訣誌髄
00 90 :91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F A0 駐舶沫・圀悃棔?
00 A0 :A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF B0
。「」、・ヲァィゥェォャュョッー
00 B0 :B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF C0 アイウエオカキクケコサシスセソタ
00 C0 :C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF D0 チツテトナニヌネノハヒフヘホマミ
00 D0 :D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF E0 ムメモヤユヨラリルレロワン゙゚珮
00 E0 :E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF F0 粤蒟跚韜・・@
00 F0 :F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF    .....

*余談ですが、上記のダンプファイルは自作(アセンブラで)のダンプ表示プログラムでとったものです。

それでは試しに、文字型変数を使ってやってみます。Chr$関数を使って1〜255まで書き込みます。


Open "new.dat" For Binary As #1   
For i = 1 To 255
a$ = Chr$(i)
Put #1, , a$
Next
Close #1

結果は、&H81〜&H9F、 &HE0〜 &HFCまでが00になってしまっており、正しく書き込めていません。
Visual Basicの仕様では上記のようなコードはBinaryファイルの出力では使えないという結果となりました。

-D
00 00 :01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 ................
00 10 :11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 ...............
00 20 :21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 !"#.%&'()*+,-./0
00 30 :31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 123456789:;<=>?@
00 40 :41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 ABCDEFGHIJKLMNOP
00 50 :51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60 QRSTUVWXYZ[\]^_`
00 60 :61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 abcdefghijklmnop
00 70 :71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F 80 qrstuvwxyz{|}~&127.
00 80 :00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 90 :00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 A0 ...............
?
00 A0 :A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF B0
。「」、・ヲァィゥェォャュョッー
00 B0 :B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF C0 アイウエオカキクケコサシスセソタ
00 C0 :C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF D0 チツテトナニヌネノハヒフヘホマミ
00 D0 :D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF 00 ムメモヤユヨラリルレロワン゙゚.
00 E0 :00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00 F0 :00 00 00 00 00 00 00 00 00 00 00 00 FD FE FF ................


4. 補足
Binaryモードで書き込みをする時に、文字列型、Byte型以外の変数を使うとどうなるのでしょうか。
試しに、整数型で実験してみます。

Dim a As Integer
Open "new1.dat" For Binary As #1    
For i = 1 To 255
a = i
Put #1, , a
Next
Close #1

結果をみてみます。

-D
00 00 :01 00 02 00 03 00 04 00 05 00 06 00 07 00 08 00 ................
00 10 :09 00 0A 00 0B 00 0C 00 0D 00 0E 00 0F 00 10 00 ................
00 20 :11 00 12 00 13 00 14 00 15 00 16 00 17 00 18 00 ................
00 30 :19 00 1A 00 1B 00 1C 00 1D 00 1E 00 1F 00 20 00 .............. .
00 40 :21 00 22 00 23 00 24 00 25 00 26 00 27 00 28 00 !.".#...%.&.'.(.
00 50 :29 00 2A 00 2B 00 2C 00 2D 00 2E 00 2F 00 30 00 ).*.+.,.-.../.0.
00 60 :31 00 32 00 33 00 34 00 35 00 36 00 37 00 38 00 1.2.3.4.5.6.7.8.
00 70 :39 00 3A 00 3B 00 3C 00 3D 00 3E 00 3F 00 40 00 9.:.;.<.=.>.?.@.
00 80 :41 00 42 00 43 00 44 00 45 00 46 00 47 00 48 00 A.B.C.D.E.F.G.H.
00 90 :49 00 4A 00 4B 00 4C 00 4D 00 4E 00 4F 00 50 00 I.J.K.L.M.N.O.P.
00 A0 :51 00 52 00 53 00 54 00 55 00 56 00 57 00 58 00 Q.R.S.T.U.V.W.X.
00 B0 :59 00 5A 00 5B 00 5C 00 5D 00 5E 00 5F 00 60 00 Y.Z.[.\.].^._.`.
00 C0 :61 00 62 00 63 00 64 00 65 00 66 00 67 00 68 00 a.b.c.d.e.f.g.h.
以下略

整数型なので2Byte単位で書き込まれているのが、わかります。

Top page | Visual Basic&Excel活用研究目次