VBでのファイルデータ取得について


冬緑茶  2003-12-25 10:18:48  No: 110943  IP: [192.*.*.*]

おはようございます。
VBでの文字列宣言の仕方についてご教授下さい。
C言語でいうChar配列のような定義方法をVBでは
どのように宣言すればよいのでしょうか。

例えばC言語でデータファイル.dat内に 文字列ABCDEFGという
データのみが格納されているとします。

Char str[8]と定義した配列にRead関数で文字列(ABCDEFG)を
取得すると以下のようなメモリーイメージになります。

str=
0   1   2   3   4   5   6   7
|---|---|---|---|---|---|---|
| A | B | C | D | E | F | G |
|---|---|---|---|---|---|---|

ch = str[2] で'C'を取得することが出来ます。

これをVBで実現するためには、どのような変数定義で
どのようなファイル取得すればよいのでしょうか。

例えばVBで以下のように試してみましたが、
どうしても???位置がわかりませんでした。
Dim str(8) As String  ←???
Open ファイル名 For Input As #ファイル番号
Line Input #ファイル番号, ???
Close #ファイル番号

結局、何がやりたいかというと
ファイルから取得したデータを指定バイト毎に切り分けて
フォーム上にある異なるコントロール(複数のテキストボックス)に
表示したいのです。

説明不足、意味がわからないところがあるかと思いますが
ご教授お願い致します。

編集 削除
SKY  2003-12-25 10:58:57  No: 110944  IP: [192.*.*.*]

ま・・・こういうものがほしいのでしょうか?

Option Explicit

Private Sub Command1_Click()
    Dim hnum As Integer
    Dim pnum As Integer
    Dim mnum As String'文字型変数宣言
    
    
    hnum = FreeFile
    Open App.Path & "\Read.txt" For Input As #hnum'指定ファイルから読み込み
        For pnum = 0 To 5
            Line Input #hnum, mnum
            text1(pnum).Text = mnum
        Next pnum
    Close #hnum
End Sub

Private Sub Command2_Click()
    Dim hnum As Integer
    Dim pnum As Integer
      
    hnum = FreeFile
    Open App.Path & "\Read.txt" For Output As #hnum’指定ファイルに保存
        For pnum = 0 To 5
           Print #hnum, pnum
        Next pnum
    Close #hnum

End Sub

テキストボックスを一個貼り付けてコピペするとコントロール配列ができますのでそれを6個つけてコマンドボタンを2個つけてやってみてくださいな

とりあえずテキストボックスに書いたことを保存したり読み出したりすることはできます

編集 削除
化石  2003-12-25 10:59:57  No: 110945  IP: [192.*.*.*]

CとVBでは配列の扱い方が違うので、そのままやろうとすると挫折しますよね(^^;
読み込むデータはテキストでしょうか?バイナリーでしょうか?
テキストだったら文字列型の単純変数にどっかり読み込んでMid()関数で必要な文字を取り出せばいいかと思います。
バイナリーの場合だったら
Dim DataBuf() As Byte でとりあえずバイト型の宣言だけして
FileLen()  関数でファイル長を取得
Redim Databuf() (malloc見たいなモノですかね)で読込に必要な量を確保します
バイナリー形式でファイルをオープンし(この辺はヘルプ見てください)
その後InputB()で読み込んだら、databuf()でアクセスできると思います
(ただしこれはバイナリーデータなので、最後に文字変換関数で上手いことアレしてください)。

編集 削除
冬緑茶  2003-12-25 11:24:18  No: 110946  IP: [192.*.*.*]

SKYさん、化石さん、ご教授ありがとうございます。
とりあえずテキストデータの読込みでしたので
Mid関数で問題解決しそうです。
確認してみます!
あと、バイナリーで取得した場合のも試してみます。

>最後に文字変換関数で上手いことアレしてください
アレって・・・ 色々試してみます^^; (strConvとか)

編集 削除
特攻隊長まるるう  2003-12-25 11:36:30  No: 110947  IP: [192.*.*.*]

バイト型もあるけどね。

    Dim mNum() As Byte 'バイト型変数宣言

でもファイルの読み取りとか含めて VB で扱うには
String の方が何かと便利だと思ってますが…。
あとはバイト型を対象とした文字列操作関数で切り分けるとか…

対象 | String | Byte
----------------------------------
     | Asc    | AscB
     | Chr    | ChrB
     | Input  | InputB
     | InStr  | InStrB
     | Left   | LeftB
     | Right  | RightB
     | Len    | LenB
     | Mid    | MidB

編集 削除
SKY  2003-12-25 11:36:57  No: 110948  IP: [192.*.*.*]

失礼・・・今試したら失敗してた^^;
Option Explicit

Private Sub command3_Click()
    Dim nnum As Integer
        
        For nnum = 0 To 5   'textBoxの0〜5までを空白にする
            text1(nnum).Text = ""
        Next nnum


End Sub

Private Sub command2_Click()
    Dim fnum As Integer
    Dim nnum As Integer
    Dim hnum As String
    
    fnum = FreeFile
    
    Open App.Path & "\24.txt" For Input As #fnum
        For nnum = 0 To 5
            Line Input #fnum, hnum  '1行づつ改行するまで読み込む
            text1(nnum).Text = hnum       'textBoxの0〜5まで繰り返し
        Next nnum
    Close #fnum
    
    
End Sub

Private Sub command1_Click()
    Dim fnum As Integer
    Dim nnum As Integer
    
    fnum = FreeFile
    
    Open App.Path & "\24.txt" For Output As #fnum
        For nnum = 0 To 5
            Print #fnum, text1(nnum).Text 'textboxの0~5まで保存
        Next nnum
    Close #fnum
    
End Sub

これなら大丈夫なはず・・・

編集 削除
魔界の仮面弁士  2003-12-25 11:37:00  No: 110949  IP: [192.*.*.*]

> C言語でいうChar配列のような定義方法をVBでは
> どのように宣言すればよいのでしょうか。

C言語のChar配列、すなわち「文字の配列」は、他の言語においては、
「文字列」という概念で処理される事が多いです。

「文字列」としての意味であれば、
   Dim S As String
   S = "ABCD"
とだけ書けばOKです。

しかし何らかの理由で、「文字列」ではなく、Cのように「文字の配列」として
扱いたいならば、以下のようにします。

まず、VB.NET であれば、
  Dim C() As Char
のように定義します。Char型は、特定の1文字を表すデータ型です。

この変数に一括代入するなら、
  C = New Char() {"A"c, "B"c, "C"c, "D"c}
のように、一文字ずつ指定していくか、もしくは
  C = "ABCD".ToCharArray()
のように、文字列(String型)のToCharArrayメソッドで変換します。
(もっとも、今回の質問文から察するに、.NETでは無さそうですけれども)


VB6以下、あるいはVBAの場合は、C言語の Char に相当するデータ型は
ありません。強いて言えば、固定長文字列型を使って、
    Dim C() As String * 1
    ReDim C(3)
    C(0) = "A"
    C(1) = "B"
    C(2) = "C"
    C(3) = "D"
と書けば、C言語の Char に近いイメージになりますが、メリットは無いでしょう。
まぁ、APIを使うためには、C言語の char型(≠Char型)に相当する
「Byte型」の配列で代用する事はありますけれどね。

String型をByte型配列に変換する場合は、
   Dim C1() As Byte
   C1 = "ABCD"
もしくは、
   Dim C2() As Byte
   C2 = StrConv("ABCD", vbFromUnicode)
という形式を使います。
(前者はUnicode文字列、後者はShift_JIS文字列のバイトデータになります)


> Dim str(8) As String  ←???
> Open ファイル名 For Input As #ファイル番号
> Line Input #ファイル番号, ???
> Close #ファイル番号
Line Input #を使う場合は、「文字の配列」ではなく「文字列」にします。

つまり、
  Dim S As String
で宣言して、
   Line Input #ファイル番号, S
という感じですね。


> ファイルから取得したデータを指定バイト毎に切り分けて
バイト単位ならば、(C言語の)Char ではなく、charなのでは?
Charだとしたら、「文字単位」ですよね。

文字単位で扱いたいなら、Mid関数を使ってみて下さい。
   C = Mid("ABCD", 1, 1)   'Cには "A" が入る。
   C = Mid("ABCD", 2, 1)   'Cには "B" が入る。
   C = Mid("ABCD", 3, 1)   'Cには "C" が入る。

バイト単位で扱いたいなら、先に記述した方法で、Stringデータを
Byte配列に変換してみてください。あるいは、Open For Input ではなく、
Open For Binary を使えば、最初からByte配列にて得る事もできます。

編集 削除
冬緑茶  2003-12-25 18:16:27  No: 110950  IP: [192.*.*.*]

SKYさん、特攻隊長まるるうさん、化石さん、魔界の仮面弁士さん、アドバイスありがとうございます。

シーケンシャルによるデータ読込みは以下の内容で出来ました。
--- 外部ファイル(SampleData.Dat) ---
11111あああああ0000000001

--- 画面コントロール ---
Text1, Text2, Text3  → 配列化(0〜2), 配列名→Text
Command1

--- General領域 ---
TYPE SAMPLE
  m_xxx As String
  m_yyy As String
  m_zzz As String
END TYPE

Sub Command1がクリック時
  Dim 格納配列 As String
  Open "F:\SampleData.Dat" For Input As #ファイル番号
  Line Input #ファイル番号, 格納配列
  Call 表示関数(格納配列)
End Sub

Sub 表示関数(str As String)
  Dim sample As SAMPLE
  Dim i As Integer

  sample.m_xxx=Mid(str, 1,  5)
  sample.m_yyy=Mid(str, 6, 10)
  sample.m_zzz=Mid(str,16, 10)

  <中略>

  Text(0).Text=sample.m_xxx
  Text(1).Text=sample.m_yyy
  Text(2).Text=sample.m_zzz
End Sub

上記で表示することができましたが
別のデータファイル(文字コードの複合)をバイナリーモードで
(複合といっても上記のデータファイルで'あああああ'がUnicodeです)
取得しようとすると以下のエラーがでました。

Dim sz As Long
Dim bstr() As Byte
Open ファイル名 For Binary Access Read As #ファイル番号
sz=LOF(ファイル番号)
ReDim bstr(sz-1)
Get #ファイル番号, ,bstr

Call 表示関数(bstr)    ←ここで "ByRef引数の型が一致しません"と出てしまう
※構造体は上記と同じ構造を使用します(TYPE SAMPLE)
※構造体内の変数型も同様です

Sub 表示関数(bstr() As Byte)
  Dim sample As SAMPLE

  sample.m_xxx=Mid(bstr, 1,  5)   ←ここ以前でエラーなので自信なし
  sample.m_yyy=Mid(bstr, 6, 10)
  sample.m_zzz=Mid(bstr,16, 10)
  
End Sub

すいません、お気付きの点がありましたらご教授お願いします。
非常に長くなってしまい申し訳ありません。。

編集 削除
魔界の仮面弁士  2003-12-25 18:42:01  No: 110951  IP: [192.*.*.*]

> "ByRef引数の型が一致しません"と出てしまう

ByRef定義された引数に、(式や定数ではなく)変数を渡す場合、
呼び出し側と呼び出される側のデータ型が一致していないと、
そのようなエラーが発生する事になります。

# 引数に、ByVal / ByRef の指定が無い場合、
# VB6では「ByRef」扱いとなります。


例えば、

Option Explicit

Private Sub Form_Load()
    Dim bstr() As Byte
    ReDim bstr(3)
    Call Test(bstr)
End Sub

Private Sub Test(bstr() As Byte)
    MsgBox "Test"
End Sub

というコードは正しく呼び出されますが、呼び出されるプロシージャを
  Private Sub Test(bstr As Byte)
などという定義にした場合には、『ByRef引数の型が一致しません』の
エラーが発生するはずです。

編集 削除