文字列型とバイト配列の連結について

解決


生茶  2005-06-29 02:38:14  No: 123128

度々申し訳御座いません。

過去ログを拝見致しましたが、どうしても上手く行かず投稿させて頂きました。

文字列="ABCDEFGHIJ"(固定長)

バイナリデータ:バイト配列
00 00 00 00 00 00 FC 01 30 30 30 30 30 00(可変長)

上記を連結させWinsockにて送受信を考えております。

そこで、文字列型とバイト配列を連結させる方法をご教授願えませんでしょうか。

Private Const InputFile     As String = "C:\etude\Log\InFile.etw"
Private Const OutputFile    As String = "C:\etude\Log\OutFile.etw"

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
            (Destination As Any, Source As Any, ByVal Length As Long)
            
Private Sub Command1_Click()

    Dim Buff()              As Byte
    Dim lngFileSize         As Long
    Dim intFileNo           As Integer
    Dim lngTotalLen         As Long
    Dim lngWorklen          As Long
    Dim OutWork             As Work
    
    With OutWork
    
    .strWork = "ABCDEFGHIJ"  '文字列データの代入

    'バイト配列として入力
    intFileNo = FreeFile
    Open InputFile For Binary As intFileNo
        lngFileSize = LOF(intFileNo)
        ReDim Preserve .bytBinary(lngFileSize) As Byte 'メモリー再確保
        .bytBinary() = InputB(lngFileSize, intFileNo)
    Close intFileNo
    
    lngTotalLen = (LenB(.strWork) + lngFileSize) - 1
    
    ReDim Preserve Buff(lngTotalLen) As Byte    'メモリー再確保
    
    Call CopyMemory(Buff(0), OutWork, lngTotalLen)    'API使用(構造体の代入)
   
    'バイト配列を出力
    intFileNo = FreeFile
    Open OutputFile For Binary Access Write As #intFileNo
        Put #intFileNo, , Buff
    'ファイルを閉じる
    Close #intFileNo

    End With
End Sub

●構造体定義
Type Work
    strWork                     As String * 10
    bytBinary()                 As Byte
End Type

●出力結果
41 42 43 44 45 46 47 48 49 4A 46 00 E8 66 19 00 E0 AE 1E 00 00 00 00
00 00 00 00 00 80 00 00 00 C4 00

"ABCDEFGHIJ"は正常に出力されておりますが、その後のバイト配列が上手く
出力されておりません。

どなたか原因をご存知の方いらっしゃいましたらご教授を宜しくお願い致します。

環境はVB6.0、WindowsXPです。

宜しくお願い致します。m(__)m


K.J.K.  2005-06-29 06:13:10  No: 123129

Dim abSendData() As Byte
    Dim sSource As String
    Dim abSource() As Byte
    
    sSource = "ABCDEFGHIJ"
    ReDim abSource(0& To 13&) As Byte
    abSource(6&) = &HFC
    abSource(7&) = &H1
    abSource(8&) = &H30
    abSource(9&) = &H30
    abSource(10&) = &H30
    abSource(11&) = &H30
    abSource(12&) = &H30

    ' ...
    
    abSendData = StrConv(sSource, vbFromUnicode) & CStr(abSource)

文字列と非文字情報が入り混じるファイルから読み込む・ファイルに書き込むときは、一括してByte型の配列で読み書きして、必要に応じて文字列方にStrConvで変換する方が楽でしょう。

で、Byte型配列を読み込むときは、ReDimでサイズが確定しているのであれば、Getで取得する方がいいのでは。


生茶  2005-06-29 19:35:03  No: 123130

K.J.K.様
  ご回答有難う御座います。

Get関数が使えるのですね。知りませんでした。試みてみます。

また質問が曖昧で申し訳御座いませんでした。

ファイルから読み込むBinaryデータは、Max32Kの可変長です。
従いまして、
1)一括してバイト配列へ格納したい。(GetやInputB?)
2)コードの中で作成したHeader情報(今回で言えば、"ABCDEFGHIJ")を連結
3)Winsockにて送信
を行いたいと考えております。
※ファイルから読み込んだデータはRAWデータとしてホストコンピュータへ
送信しますので編集は御座いません。(文字列連結を除いて)
文字列型と連結が出来れば問題ないのです。
また受信時も同様に、RAWデータのままファイル出力致します。

実現は可能ですよね?
何やら自信がなくなってきました・・・
申し訳御座いませんが引き続き宜しくお願い致しますm(__)m


K.J.K.  2005-06-29 21:19:10  No: 123131

提示したコードを確認したのでしょうか?


生茶  2005-06-29 23:25:47  No: 123132

K.J.K.さま

申し訳御座いません。
まだ初心者の為、理解に苦しんでおりました。

頂いたコードにてファイルへ出力しましたところ、バイナリデータが壊れる
ことなく出力されております。

出力結果
41 42 43 44 45 46 47 48 49 4A 00 00 00 00 00 00 
FC 01 30 30 30 30 30

バイナリデータを&H(16進数から10進数?)でバイト配列へ格納
(すみません。&の使い方がまだよくわかっておりませんが・・・)⇒
Cstr関数にてバイト配列からいったん文字列型へ変換、そして他の文字列と
連結させ、バイト配列へ代入しているところまでは理解?致しました。

それらを踏まえた上で、可変長のバイナリデータを扱うには。なのですが、

ファイルから入力したバイナリデータを一度バイト配列として読み込む。
読み込む際に&Hにて10進数へ変換、バイト配列へ入れる。
または、バイト配列で読み込んだ16進数を&Hにて他のバイト配列へ代入する。

10進数となった配列データをCstr関数にて文字列型へ変換する。
他の文字列型と連結させ、SendData(バイト配列)を作成する。

頂いたコードでは、配列一つずつに値を代入しておりますが、一括して
代入することが、現在の私の懸案事項です。。

もし認識が間違っておりましたら、ご指摘頂けますと幸甚です。

長文となってしまい申し訳御座いません。


特攻隊長まるるう  2005-06-29 23:47:09  No: 123133

>頂いたコードでは、配列一つずつに値を代入しておりますが、一括して
>代入することが、現在の私の懸案事項です。。
理由や目的も書いた方がいい。
>まだ初心者の為、理解に苦しんでおりました。
その認識があるなら、まずは自分でコーディング(理解)できる
ソースコードで実現する事が大事。配列をループで1つ1つ
設定するのでは何がまずいの?『自分の実力向上のため』とか
いう理由でも立派な理由になります。ただしこれも、べたべたな
プログラムでいいから実現できてからの話。ひとまず実現できて
から、より上級の上手いコーディングを目指すのが筋では?

現状では生茶さんの実力に合わせて K.J.K.さんが回答をくれてる
のに無視してる感じさえしてしまいます。


生茶  2005-06-30 00:28:38  No: 123134

特攻隊長まるるう様、K.J.K.様

  失礼がありました事を深くお詫び致します。

>>頂いたコードでは、配列一つずつに値を代入しておりますが、一括して
>>代入することが、現在の私の懸案事項です。。
>理由や目的も書いた方がいい。
理由ですが、前述させて頂いたMAX32Kのデータを一つずつループさせる事に
ついて、負荷を心配しております。違う方法で代入できる方法がないかと
模索しておりました。
ループ処理を試したわけではありませんので、テストしたいと思います。

>>まだ初心者の為、理解に苦しんでおりました。
>その認識があるなら、まずは自分でコーディング(理解)できる
>ソースコードで実現する事が大事。配列をループで1つ1つ
>設定するのでは何がまずいの?『自分の実力向上のため』とか
>いう理由でも立派な理由になります。ただしこれも、べたべたな
>プログラムでいいから実現できてからの話。ひとまず実現できて
>から、より上級の上手いコーディングを目指すのが筋では?

>現状では生茶さんの実力に合わせて K.J.K.さんが回答をくれてる
>のに無視してる感じさえしてしまいます。

K.J.K.様
大変申し訳御座いませんでした。
無視しているつもりは全く御座いませんが、
少し焦っており、頂いた回答にまともな返事が出来ずにおりました。

特攻隊長まるるう様
既にべたべたなプログラムとなっておりますが、引き続き事項啓発に精進
したいと思います。
ご指摘有難う御座いました。


K.J.K.  2005-06-30 03:49:13  No: 123135

# 巧言令色、鮮矣仁?

私が提示したコードで重要なのは、最後の1行だけですよ。
それを見落としているように思えます。で読み込みはGetで。
この2点を試してみたのでしょうか?

プログラマであるのであれば、日本語を介して理解しようと
するのではなく、ソースコードをそのまま理解するように
しましょう。そうしないと、日本語 <-> VBコードの相互変換
ができないままになってしまいます。


生茶  2005-06-30 19:28:55  No: 123136

K.J.K.様

巧言令色ですか・・・

頂いたコードですが、もちろん試させて頂きました。

Getステートメントにてバイナリファイルの読み込みが出来る事は
確認済みです。

ご掲示頂きました最後の行ですが、
>    abSendData = StrConv(sSource, vbFromUnicode) & CStr(abSource)

abSourceの配列の中身を一つずつループで確認し、
10進数の数値データが格納されているところまで確認しました。(FC⇒252)
それを、Cstr関数にて文字へ変換するのは文字列型として連結する為と思いますが、
この場合、String型の変数へ値を代入し、且つANSI文字へ変換されている
わけではないので、データは壊れないのですね。
「文字列型 (String) 変数にバイナリ データを格納した場合は、ANSI 文字
と Unicode 文字との間で変換が行われた場合に、データが破壊されます。」
とMSDNライブラリにありましたのでString型へ変換することに躊躇しておりました。

StrConv処理ですが、MSDNで確認したところ、引数vbFromUnicodeは
「文字列を Unicode からシステムの既定のコード ページに変換します。」
とありました。システムの規定のコード??。
VB6では文字列をUnicodeで持っていて、それをシステムの規定のコードへ
変換している・・その必要性がまだわからない状況です。

掲示板では顔や仕草などが伝わらないので、つい日本語に頼ってしまいます。
上記は、ソースコードの理解に勤めた結果とご理解頂きたいです。


特攻隊長まるるう  2005-06-30 20:47:25  No: 123137

Σ(‾□‾)論語だっ

まー。横レスする時は話の流れだけで、質問の詳細まで目を
通してない事も多いんですが(ぉぃ
Binaryデータは既存のファイルから提供されるのね(汗)
…え?ループ処理って最終的には必要無い???(滝汗)

理解を深めるのは結構ですが、解決した問題は
『〜で解決しました』という文章が書かれて無いと分かりません。
…で、基本は1スレッドにつき1つの質問です。
で、解決するまで次の質問はしない。勉強不足による
勘違いで説明の2度手間が起こり易いからです。…で、
質問が最初の質問とすりかわって継続されてませんか?

回答を読む間に新たな疑問が出てきた場合、質問をする前の
段階からはじめるよう心掛けて下さい。それなりに努力が見受け
られれば回答者側も注意したりしませんが、自分が書き込みを
行ったスレッドは[解決]まで面倒を見たいと思うのが回答者側の
心理です。ゴールを勝手にはるか先に変えられるとなんと言うか
…萎えます(  _)_ぺたり

[手順]
ここの掲示板の過去ログは充実してるから、
1:まずVBのヘルプで調べる
2:ここの過去ログ検索
…の順で調べればありがちな問題はほとんど自力で解決できます。で、
3:掲示板に質問として書き込み
です。

バイナリデータを今後も扱っていくなら、過去ログ検索
『バイナリ』で引っ掛かるスレッドに”全て”目を通して
おくと、後々楽になると思われます。
↓なんかも引っ掛かりました。
http://madia.world.coocan.jp/cgi-bin/VBBBS2/wwwlng.cgi?print+200502/05020065.txt
>で、Byte型配列を読み込むときは、ReDimでサイズが確定しているのであれば、Getで取得する方がいいのでは。
とか助言を受けたら1:VBのヘルプで…2:過去ログ検索『Get』。
引っ掛からなかったらぐーぐる検索辺りに手を広げる。…そんなクセを
付けておきませう。
>「文字列を Unicode からシステムの既定のコード ページに変換します。」
>とありました。システムの規定のコード??。
過去ログ検索『コードページ』や『魔界の仮面弁士』さんwなどでどうぞ。
>日本語環境のコードページは CP932(Shift_JIS)です
などの情報が引っ掛かります。その辺を深く調べる気ならかなり時間が掛かると
思うけど?。…今回の質問には必要なのかな?日本語で読み書きするなら
Shift_JIS でないと読めない…くらいの認識でいいんじゃないかと?

>理由ですが、前述させて頂いたMAX32Kのデータを一つずつループさせる事に
>ついて、負荷を心配しております。
CPUの負荷だけが心配ならループ内で適時 Sleep するだけで解決
してしまう事もありますし…大した問題じゃない気がしますが(  _)_ぺたり
解決したのか問題じゃ無くなったのか調べてないのか…はふ。
解決済みの問題と調査中の問題と掲示板で質問すべき問題を分けて欲しいです。

このスレッドを閉じる必要はありません。文字列型とバイト配列の連結プログラム
が完成するまで質問を繰り返して頂いて構いません。厳密に今回ボクの書いたことを
守る必要もありません。ただ、少し意識しておいて欲しい事です。


生茶  2005-07-01 20:19:43  No: 123138

特攻隊長まるるう様

  返信が遅くなり申し訳御座いません。

今回の質問では、K.J.K.様に頂いたコードにて実装できましたので、
ループ処理は必要なくなりました。(⇒解決です。)

ヘルプや過去ログは最初に必ずチェックしております。
しかし見ているつもりになっていたのですね。

このスレッドの質問に対する答えは既に出ております。(⇒K.J.K.様のコードより)
よって、解決とさせて頂きますが、
これまで誤解を解きたいという思いからスレッドを閉じることがどうしても
出来ませんでした。火に油を注いでしまったようにも思いますが・・・

しかし、また解らない事があった時は遠慮なく(ご指摘を踏まえた上で)
質問させて頂きます。その際もどうぞ宜しくお願い致します。m(__)m

K.J.K.様
有難う御座いました。


※返信する前に利用規約をご確認ください。




  


  このエントリーをはてなブックマークに追加