バイナリファイルに初めて挑戦しています。
仮にSAMPLE.datというファイルについて
バイナリエディタで表示されたデータが次のような場合
00000000 | 00 00 00 01 | 00 00 00 02 | 00 00 00 03 |
Option Explicit
Private Type SAMPLE
LONG1 As Long
LONG2 As Long
LONG3 As Long
End Type
Private Sub Command1_Click()
Dim IN_DATA As SAMPLE
Open "SAMPLE.dat" For Binary As #1
Get #1, 1, IN_DATA
Close #1
Debug.Print "LONG1 = " & Hex(IN_DATA.LONG1)
Debug.Print "LONG2 = " & Hex(IN_DATA.LONG2)
Debug.Print "LONG3 = " & Hex(IN_DATA.LONG3)
Debug.Print "LONG1 = " & IN_DATA.LONG1
Debug.Print "LONG2 = " & IN_DATA.LONG2
Debug.Print "LONG3 = " & IN_DATA.LONG3
Enn Sub
で確認したところ
LONG1 = 1000000
LONG2 = 2000000
LONG3 = 3000000
LONG1 = 16777216
LONG2 = 33554432
LONG3 = 50331648
となります。
LONG1 = 1
LONG2 = 2
LONG3 = 3
LONG1 = 1
LONG2 = 2
LONG3 = 3
を期待していたのですが、まったく予期しない結果でした。
使いたいデータは、10進数で1・2・3なのですが、これでは使えません。
多分Longの上下が自分で期待していたものとByte単位で逆になっていると
思われますが、この場合、どうやって期待通りの値を得ればよいのでしょうか。
1.Get #1, 1, IN_DATA あたりが間違っているのか。
2.Type の宣言が間違っているのか。
3.かなりややこしいビット演算で変換する必要があるのか。
こんへんのヒントだけでもお願いできませんでしょうか。
3.であれば現在の実力では、ちょっと無理かなあって思いますが、よろしくお願いします。
小人と大人、リトルエンディアンとビッグエンディアンについて調べてください。
単純にマルチバイトデータを逆順にしたいのなら、
WinAPIのCopyMemory()か、WinSock2のhtonl()かntohl()あたりを調べてみてください。
ガッありがとうございます。
調べて見ましたが・・・いまだ混乱中です。
迅速なご指導ありがとうございました。
もう少しじっくり考えてみます。もう少し見守ってください。
>ガッありがとうございます。
失礼しました。訂正します。
ガッ様ありがとうございます。
やっぱりかなり混乱中!!!。
んー…分けるだけなら簡単に出来るのですけどねぇ…
逆にLong値を作るときにちょっと問題がありまして。
VB6のLong型は符号有りですから…
というわけで、なんとなく作ってみました:
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As Any, Source As Any, ByVal Length As Long)
Public Function revOrder(ByVal L As Long) As Long
Dim buf(1 To 4) As Byte
'L先頭アドレスから4バイトを
'buf(1)の先頭アドレスから4バイトの部分にコピー
CopyMemory buf(1), L, 4
'buf(1)とbuf(4)を入れ替える
buf(1) = buf(1) Xor buf(4)
buf(4) = buf(1) Xor buf(4)
buf(1) = buf(1) Xor buf(4)
'buf(2)とbuf(3)を入れ替える
buf(2) = buf(2) Xor buf(3)
buf(3) = buf(2) Xor buf(3)
buf(2) = buf(2) Xor buf(3)
'revOrderにbufをコピー
CopyMemory revOrder, buf(1), 4
End Function
Private Sub Form_Load()
Debug.Print Hex(revOrder(&H12345678))
End Sub
値のスワップ部分は勘で書いたので、心配が残ります…
ガッ様ありがとうございます。
CopyMemoryの意味を確認させてください。
1.1回目のCopyMemoryで
Long を Byte に分けて代入("代入":表現が間違っているかも)
2.Byte毎に並びを逆に変更する
3.2回目のCopyMemoryで
Lnog に並び変えたByte * 4 を代入
っていう解釈であっていますでしょうか。
実際のテストは、VB6.0の環境で明日テストしてみます。
本当に迅速なご指導ありがとうございます。
> ガッ様ありがとうございます。
>
> CopyMemoryの意味を確認させてください。
>
> 1.1回目のCopyMemoryで
> Long を Byte に分けて代入("代入":表現が間違っているかも)
ちょっと違いますがおおむね合ってます。
メモリ上に、例えば
アドレス
00 01 02 03 ...
値 03 04 05 06 ...
と並んでいたとき、"00番地"から"4バイト"を"n番地にコピー"するといったことをします。
ここから先は、APIを呼び出す場合の知識が入ってくるので、割愛させていただきます(ぇ
※"APIを呼び出す場合の知識"はMSDNに詳しく載っています。
> 2.Byte毎に並びを逆に変更する
これは完全に違います。
並びを逆にしているのは、私が実装しました。
buf(..)=buf(??) xor buf(???)
という付近がスワップ処理で、スワップによって順番を変えています。
> 3.2回目のCopyMemoryで
> Lnog に並び変えたByte * 4 を代入
1.と同様に、あるアドレスか4バイトをコピーしているだけです。
> 実際のテストは、VB6.0の環境で明日テストしてみます。
> 本当に迅速なご指導ありがとうございます。
でゎ、がんばってください。
…ん、もしかして…
1. 2. 3.でそれぞれCopyMemoryについて訊いたのではなくて…
プログラムコードの解説をしていました…?
↑なんかそれっぽぃ…
orz また早とちりしてしまいました;
スミマセン(TT
ガッさま 結果報告が遅れて申し訳ありませんでした。
結果は「解決」です。
意味も理解できました。
過去ログを参照される方のために、一様解決ですが、実際
に手作業で確認したプロセスを記載させていただきます。
実際にBuf(1)とBuf(4)の入れ替えを手作業で確認してみました。
CopyMemory Buf(1), LONG, 4 でLONGをBuf(1).....Buf(4)に代
入後の結果を仮に
Buf(1)=0A Buf(2)=01 Buf(3)=00 Buf(4)=01 として
■Buf(1) = Buf(1) Xor Buf(4) = 0A Xor 01
0000 1010 = 0A
0000 0001 = 01
---------------
0000 1011 ⇒ Buf(1) = 0B
■Buf(4) = Buf(1) Xor Buf(4) = 0B Xor 01
0000 1011 = 0B
0000 0001 = 01
---------------
0000 1010 = 0A ⇒Buf(4) = 0A Buf(4) 入替え完了
■Buf(1) = Buf(1) Xor Buf(4) = 0B Xor 01
0000 1011 = 0B
0000 1010 = 0A
---------------
0000 0001 = 01 ⇒Buf(1) = 01 Buf(1) 入替え完了
※Buf(2)とBuf(3)は記載を省略します。
入替えたBuf(1)......Buf(4)をLong型変数に代入
CopyMemory LONG, Buf(1), 4
ガッさまご親切なご指導ありがとうございました。
ツイート | ![]() |