Line Inputで読込んだString型の文字列があります。
特に区切り文字がない、固定長のデータなので、1個1個数字を指定して
必要な部分を取出せばいいのですが、数が多いのでそのまま構造体の変数
として見る事は出来ないか?と考えています。 VB6で可能でしょうか?
<イメージ例>
Type KOU_TEST
Double1 As String * 1
Code1 As String * 5
Double2 As String * 1
Conmma1 As String * 1
Double3 As String * 1
Code2 As String * 5
Double4 As String * 1
Conmma2 As String * 1
Double5 As String * 1
Code3 As String * 5
Double3 As String * 1
End Type
Dim aaa As KOU_TEST
Dim bbb as String
bbb=""aaa","bbb","ccc""
aaa=bbb ←この様なイメージでコピーしたい。
その後、下記の様に通常の構造体として、必要な部分のみ利用したいです。
aaa.Code1
aaa.Code2
aaa.Code3
> Type KOU_TEST
って、事はVB6までですよね?
でしたら、「構造体」では無く、「ユーザー定義型」ですね。
文字列型からユーザー定義型へのキャスト(コピー)はできませんが、
ユーザー定義型からユーザー定義型ならできます。
つまり、
------------------------
Private Type X
X As String * 23
End Type
------------------------
の様な、同じサイズのユーザ定義型を、もう一つ用意しておけば、
「LSet ステートメント」でコピーできます。
あれ、
> 特に区切り文字がない、固定長のデータなので
って事なのに、
> bbb=""aaa","bbb","ccc""
って?
区切り記号(,)はあるし、*5のはずなのに、3文字しかない。
Open "hogege.txt" For Random As #intFileNum Len = Len(aaa)
Get #intFileNum, 1, aaa
直接ランダムアクセスで読んではいけないのかな。
【大吉末吉様】
>ユーザー定義型からユーザー定義型ならできます。
>「LSet ステートメント」でコピーできます。
ありがとうございます。これでやってみます!
>区切り記号(,)はあるし、*5のはずなのに、3文字しかない。
すいません。
説明用に作ったデータに誤りがありました。
5→3で、(,)はありません。
【我龍院様】
>Open "hogege.txt" For Random As #intFileNum Len = Len(aaa)
>Get #intFileNum, 1, aaa
ランダムアクセスで読込んだのですが、レングスはあわせた筈なのに、
上手く各項目に値がセットされなかった次第です。
そこで、LineInputでスキャンし、スキャン後のデータを構造体へキャ
スト出来ないかなと思っておりました。
ちなみに、固定長文字を切り出す時、不思議な現象が発生してます。
Dim aaa,bbb as String
aaa = "12345678テストU,H,A,G,K,B,ph "",123456789"
bbb = MidB(aaa, 1, 128)
この様に、変数aaaの文字列の中から、最初のダブルクォーテーション部分(64バイト)の文字をMidB関数で切り出し、bbb関数へ格納しようとしています。
UNICODEになるらしいので、倍の128を指定してるのですが、ダブルクォーテーション以降の文字も入ってしまいます。
全部半角文字と区切り文字が混在する、固定長文字列の切り出しは、どうすべきなのでしょうか?
ウン−、混乱ですね。
一つずつやっていきましょう。
>Dim aaa,bbb as String
これは
Dim aaa as String , bbb As String ですよね。
>aaa = "12345678テストU,H,A,G,K,B,ph "",123456789"
「""」を「"〜"」の中で使うと、最初の「"」はエスケープキャラクタになります。
詳しくは、MSDNの「文字列内のクオーテーション マーク」を参照してください。
> ランダムアクセスで読込んだのですが、レングスはあわせた筈なのに、
> 上手く各項目に値がセットされなかった次第です。
VB6 の文字列は、Unicode として保持されるとは言っても、ファイルへの
入出力時などにおいては、VB2 の文字列同様、Shift_JIS に変換されます。
VB6 の場合、String * 2 が「2 文字」を意味しますので、漢字等が
含まれるデータの場合、文字コード変換に伴うデータサイズのずれを
考慮せねばなりません。
そのため、
> Open "hogege.txt" For Random As #intFileNum Len = Len(aaa)
で開いた場合、問題が出てくるかと思われます。
固定長文字列型を含むユーザ定義型の、ファイル出力テスト
-------------------------
Option Explicit
Private Type T
S As String * 3
End Type
Private Sub Form_Load()
Command1(0).Caption = "バイナリ"
Command1(1).Caption = "ランダムLen=6"
Command1(2).Caption = "ランダムLen=3"
Check1.Caption = "メンバのみ出力"
Check1.Value = vbChecked
End Sub
Private Sub Command1_Click(Index As Integer)
Dim FNo As Integer
FNo = OpenFile(Index)
PutData FNo, "012"
PutData FNo, "あいう"
PutData FNo, "345"
Close FNo
End Sub
Private Function OpenFile(ByVal Index As Integer)
Const File As String = "C:\newFile.txt"
If Dir(File) <> "" Then
Kill File
End If
OpenFile = FreeFile()
Dim x As T
Select Case Index
Case 0
Open File For Binary Access Write As #OpenFile
Case 1
Open File For Random Access Write As #OpenFile Len = LenB(x)
Case 2
Open File For Random Access Write As #OpenFile Len = Len(x)
End Select
End Function
Private Sub PutData(ByVal FNo As Integer, ByVal text As String)
Dim x As T
x.S = text
If Check1.Value = vbChecked Then
Put #FNo, , x.S
Else
Put #FNo, , x
End If
End Sub
-------------------------
バイナリ、メンバのみ
→ "012あいう345"
→ 30,31,32,82,A0,82,A2,82,A4,33,34,35
ランダムLen=6、メンバのみ
→ "012###あいう345" (#部は null文字)
→ 30,31,32,00,00,00,82,A0,82,A2,82,A4,33,34,35
ランダムLen=3、メンバのみ
→ (平仮名の出力時に、実行時エラー59)
→ (レコード長が一致しません。)
バイナリ、ユーザ定義型全体
→ "012あ*345" (*部は非可読文字)
→ 30,31,32,82,A0,17,33,34,35
ランダムLen=6、ユーザ定義型全体
→ "012###あ*###345" (#部は null 文字、*部は非可読文字)
→ 30,31,32,00,00,00,82,A0,17,00,00,00,33,34,35
ランダムLen=3、ユーザ定義型全体
→ "012あ*345" (*部は非可読文字)
→ 30,31,32,82,A0,17,33,34,35
【我龍院様】
>一つずつやっていきましょう。
ありがとうございます。
>>Dim aaa,bbb as String
>これは
>Dim aaa as String , bbb As String ですよね。
その通りです。
>>aaa = "12345678テストU,H,A,G,K,B,ph "",123456789"
>「""」を「"〜"」の中で使うと、最初の「"」はエスケープキャラクタになります。
実際には「”」を含む文字列があり、そこの手前部分(64バイト)までを取り込もうとしています。
(「12345678テストU,H,A,G,K,B,ph 」←この部分)
単純に「bbb = MidB(aaa, 1, 128)」で切り出せると思っていたのですが、上手く切り出せず、質問してる次第です。
何か分かりますでしょうか?
【魔界の仮面弁士様】
>VB6 の場合、String * 2 が「2 文字」を意味しますので、漢字等が
>含まれるデータの場合、文字コード変換に伴うデータサイズのずれを
>考慮せねばなりません。
>そのため、
>> Open "hogege.txt" For Random As #intFileNum Len = Len(aaa)
>で開いた場合、問題が出てくるかと思われます。
当初、ランダムアクセスを用いて下記の様なファイルをリードしようとしてました。
/*テキストファイルの中身*/
-----------------------------------------------------------------
"あああああ","かきく,AAA","”さ”,1"
"いいいいい","かき,AAAAA","”さ”,2"
"ううううう","か,AAA,BBB","”さ”,3"
-----------------------------------------------------------------
/*プログラム*/
Type KOU_SAMPL
Double1 As String * 1
Name1 As String * 10
Double2 As String * 1
Conmma1 As String * 1
Double3 As String * 1
Name2 As String * 10
Double4 As String * 1
Conmma2 As String * 1
Double5 As String * 1
Name3 As String * 10
Double3 As String * 1
Enter As String * 2
End Type
Dim samplaaa As KOU_SAMPL
Open FNAME For Random Access Read As #Fno Len = Len(sampl)
Get #Fno, , sampl
Do Until EOF(Fno)
〜
Loop
Close #Fno
この様なファイルの場合、ランダムアクセスでのリードは不向きなのでしょうか?
「Input」や「Line Input+split関数」でも上手くできなかったので、
「Line Input+MidB関数」しかないのかな?と思い、現在に至ってます。
皆様はどうされてるのでしょうか?
<補足>
Name3 As String * 10←8の間違いです。
文字コードを意識しましょう。
> 実際には「”」を含む文字列があり、そこの手前部分(64バイト)まで
それは、「Shift_JIS バイナリとしてみた場合の 64 バイト」ですよね。
VB6 側の String 型は、Unicode バイナリで保持されますから、
MidB でバイト単位の処理を行うのであれば、
1. StrConv( , vbFromUnicode) を使い、Shift_JIS バイナリに変換
2. MidB を使い、(Shift_JIS データとしての)先頭 64 バイトを取得
3. StrConv( , vbUnicode) で、それを Unicode バイナリに復元
という手順をとらないと、意味がありませんよね。
> この様なファイルの場合、ランダムアクセスでのリードは不向きなのでしょうか?
その形式だとすれば、ランダムアクセスであれ、バイナリアクセスであれ、
固定長文字列型メンバではなく、バイト配列型メンバにすれば、
位置がずれることなく読み込ませることができますよ。ただし、
StrConv などで、文字コードの変換を行う必要がありますけど。
固定長文字列型メンバにすると、Shift_JIS/Unicode 変換が自動的に
行われるので、「文字数」と「Shift_JISでのバイト数」の差分から、
データにずれが生じてしまいます。バイナリアクセスならともかく、
ランダムアクセスでは、この点が致命的となります。
一方、バイト配列型メンバにすると、そうした自動変換が発生しないので、
データのずれは出ないため、ランダムアクセスでも有効です。そのかわり、
文字コードやデータ型の変換を、自分で行わなければならないという
不便さが残ります。
> 皆様はどうされてるのでしょうか?
固定長ファイルの読み方ですか。私は、バイナリアクセスを使った上で、
文字コードや型変換、さらに不正データの排除などを含めた処理を
記述することが多いですね。
>> Open "hogege.txt" For Random As #intFileNum Len = Len(aaa)
>で開いた場合、問題が出てくるかと思われます。
魔界の仮面弁士さん、ご指摘の通りだめですね。
最初の質問を見たときファイルベースで"固定長"と思いましたので。
>(「12345678テストU,H,A,G,K,B,ph 」←この部分)
私が調べると、「ph」までが25文字スペースが36文字計61文字となりますが。
念の為アスキーダンプしてみましたが同じですね。
49 50 51 52 53 54 55 56-31899-31912-31897 85 44 72 44 65 44 71 44 75 44 66 44 112 104
32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32
32 32 32 32 32 32 32 32 32 34 44 49 50 51 52 53 54 55 56 57
【魔界の仮面弁士様、我龍院様】
細かい情報有難う御座います。
バイナリアクセス、StrConv( , vbFromUnicode)、バイト配列型メンバ(?)は使った事ありませんが、調べてやってみます。
aaa = "12345678テストU,H,A,G,K,B,ph "",123456789"
bbb = MidB(StrConv(aaa, vbFromUnicode), 1, 64)←まだ使い方間違えてるみたいですが(汗)
追って結果報告いたします。
【魔界の仮面弁士様、我龍院様、大吉末吉様】
>1. StrConv( , vbFromUnicode) を使い、Shift_JIS バイナリに変換
>2. MidB を使い、(Shift_JIS データとしての)先頭 64 バイトを取得
>3. StrConv( , vbUnicode) で、それを Unicode バイナリに復元
こちら実現する事出来ました!!
「bbb = StrConv(MidB(StrConv(aaa, vbFromUnicode), 1, 64), vbUnicode)」
後は、バイナリアクセス、バイト配列型メンバ(?)をやってみます。
解決にするの忘れてました。
ツイート | ![]() |