プロが教えるわが家の防犯対策術!

VB.net(XP:VS2008のみフルインストール)にて
テキストファイルから入力したデータを構造体st_testに入れたいと考えているのですが、実現できません。

どなたか、お力添えをお願いします。

テキストファイルは、事前に構造体(st_test)に値を入れ、
単純にFileOpen→OutPutしています。
(","や" "などでメンバ毎に分割等はしておりません。)

構造体
----------------------
Public Structure st_test
<VBFixedArray(63), MarshalAs(UnmanagedType.ByValArray, SizeConst:=64)> _
Dim A() As Byte
Dim B As Integer
<VBFixedArray(7), MarshalAs(UnmanagedType.ByValArray, SizeConst:=8)> _
Dim N() As Byte
<VBFixedArray((7), (11)), MarshalAs(UnmanagedType.ByValArray,
SizeConst:=(72))> _
Dim S(,) As Byte
<VBFixedArray(11), MarshalAs(UnmanagedType.ByValArray, SizeConst:=12)> _
Dim U() As Integer
End Structure
----------------------

実現しようとしている個所
----------------------
Dim t As String
Dim temp(2) as st_test

FileOpen(1, "test1.txt", OpenMode.Input)
Input(FileNum, t)
'''temp(0) = CType(CType(t, Object), st_test)...?
temp(0) = CType(t, st_test)
|
FileOpen(1, "test2.txt", OpenMode.Input)
Input(FileNum, t)
temp(1) = CType(t, st_test)
----------------------

上記の様に処理を行えば簡単にできるのかと安易な発想でいましたが、
CTypeの処理で'String'の値を'st_test'に変換できません。
旨のエラーになり、うまく実現することができません。

そもそもString型のデータをst_testにキャストすることが不可能なのでしょうか?
それともただ、実現方法がカスなのでしょうか?

実際の構造体のサイズは4000Byteを超え(メンバ数も多いです。。。)
一つ一つ入力していくことが現実的に不可能なため
ファイルよりInputすることしか思いついておりません。

test1.txtの中身を秀丸で開いてみました。
参考になれば・・・。
改行はなく、"福岡"の後等にそれぞれ空白があります。
--------------------------
福岡 . A1 14 15 16 17 18 19 XX XX XX XX XX XX

--------------------------

宜しくお願いします。

A 回答 (1件)

構造体のデータを直接ファイルから読み込みたいのであれば、テキスト形式ではなくバイナリ形式であることが前提だと思います。


構造体をそのまま出力しているはずなのに、なぜテキスト形式になっているのかナゾです。。。
また、CTypeでString型からユーザー定義型への変換はできません。
仮に可能だとしても、文字列では構造体とサイズが一致しないはずです。

ファイルがバイナリで保存されていれば、
Byte配列→構造体(固定長)
の変換でファイルから読み込めます。
おおまかな手順としては、
1. ファイルから構造体の固定長分のバイナリを読み取りByte配列に格納。
2. Byte配列を構造体にMarshal.Copyでコピー
の2つになります。

[ VBコード ]
' 構造体(サイズは14バイト)
<Runtime.InteropServices.StructLayout(Runtime.InteropServices.LayoutKind.Sequential, Pack:=1)> _
Private Structure Sample
Public valueA As Integer ' 4byte
Public valueB As Short ' 2byte
Public valueC As Double ' 8byte
End Structure

' ファイルから読み込む
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim datSample As Sample
Dim bytRead(13) As Byte

' ファイルから14バイト分を読み込む
Using srmRead As New IO.BinaryReader(New IO.FileStream("C:\hoge.dat", IO.FileMode.Open, IO.FileAccess.Read))
bytRead = srmRead.ReadBytes(14)
End Using

' 構造体用のGCハンドルを用意
Dim hData As System.Runtime.InteropServices.GCHandle
hData = System.Runtime.InteropServices.GCHandle.Alloc(datSample, Runtime.InteropServices.GCHandleType.Pinned)

' Marshal.Copyでバイト配列から構造体(のポインタ)へコピー
Call Runtime.InteropServices.Marshal.Copy(bytRead, 0, hData.AddrOfPinnedObject, bytRead.Length)

' コピーされた構造体のデータ(hData.Target)を変数に格納
datSample = CType(hData.Target, Sample)

' ハンドル解放
Call hData.Free()

' 構造体のデータを出力
TextBox1.Text = datSample.valueA.ToString("x8") & ":" & datSample.valueB.ToString & ":" & datSample.valueC

End Sub


[ hoge.datの内容(16進数表記) ]
78 56 34 12 F6 FF 77 BE 9F 1A 2F DD 5E 40


[ TextBox1の出力結果 ]
12345678:-10:123.456


ファイルがテキスト形式で保存されてしまっている場合は、まずテキストを構造体のメンバー順に対応したバイト配列に変換する必要があります。


もうひとつは、System.Reflectionを使って構造体のメンバーを列挙し、順番にデータを放り込む方法もありますが、思いついただけでコード化していないのでここでは詳しく書きません。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!