• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:VB2005 で NetworkStream で取得したデータのバイト数の取得方法について)

VB2005でNetworkStreamで取得したデータのバイト数の取得方法について

chie65536の回答

  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.1

>LsLen = LNetworkStream.Read(LucData, 0, LucData.Length) >LstrText = System.Text.Encoding.UTF8.GetString(LucData, 0, LsLen) この2行の意味、理解してますか? 1行目:LucDataの位置に、LucDataのサイズ(10000バイト)分、読み込んで、結果として「読み込んだバイト数」をLsLenに格納する。 2行目:LucDataの位置の「さっき読んだバイト数(LsLen)」の分のデータを、UTF8の文字列と思ってエンコードして、結果文字列をLstrTextに格納する。 >最後、10000バイトに満たない場合、取得したデータのバイト数が知りたいです。 「取得したデータのバイト数」とは何か? 「LsLen」には何が格納されているか? この2点を「よ~く考えて」みましょう。 それと「10000バイトづつ読んで、最後だけ10000に満たない」と思っているようですが、そんな事はありません。仕様書のどこにも必ずそうなるとは書かれていません。 もしかしたら「1回目は9997バイト、2回目は9996バイト、3回目は3521バイトで終了」って可能性もあります。 あと、この読み込み処理はバグってます。根本的な変更が必要です。 「1回目の読み込みの10000バイト目に、多バイト文字の第1バイトが来て、2回目の読み込みの1バイト目に、多バイト文字の第2バイト以降が来たら、どういう結果になるか?」を考えてみて下さい。 例えば、全角文字の「あ」は、UTF8では16進で「E3、81、82」の3バイトになります。「あ」を3335文字送ると「E3、81、82」が3335回繰り返した、10005バイトのデータが送られます。 読み込みは10000バイト単位で繰り返すので、1ブロック目のデータは 00001:E3 00002:81 00003:82 00004:E3   | 09997:E3 09998:81 09999:82 10000:E3 ☆ になり、2ブロック目のデータは 10001:81 ☆ 10002:82 ☆ 10003:E3 10004:81 10005:82 になります。 すると、System.Text.Encoding.UTF8.GetStringは、上記の☆が付いたデータを、正しく「あ」にエンコードできません。 つまり、貴方が書いたプログラムは「10000バイト単位に、他バイト文字が文字化けし、正しく受信できない」と言うバグがあるのです。 ですので、System.Text.Encoding.UTF8.GetStringで文字コードのエンコードを行う際は「全部のデータを取得し終わってから、最後に1回だけ、一気に行う必要」があります。 それが不可能であれば「改行コードなど、絶対に多バイト文字じゃない文字で区切ってreadする」、つまり、「1行ごとに読み込みを繰り返す」などの処理が必要でしょう。 ともかく、バグってて使い物にならないので、上司から指摘されて恥をかく前に、全面的に作り直しましょう。

mountain11
質問者

お礼

お恥ずかしいソースにも関わらず、丁寧なご説明、ありがとうございました。 教えていただいたとおり、文字コードのエンコードは、全部のデータを取得し終わってから行うよう修正しました。 しかし、Formなら正しく動くのですが、Serviceにすると正しく動きません。 LNetworkStream.DataAvailable が、FormだとTrueの所が、 サービスだとFalseと判定して、データの途中で読み込みを終了してしまいます。 下記が、データを取得部分のソースです。 Do LNetworkStream = objClient.GetStream() Redim LucData(100000) '受信データの読み出し LsLen = LNetworkStream.Read(LucData, 0, LucData.Length) Redim Preserve LucTotalBytes(LsTotalLen + LsLen) 'データを連結する For LiCnt = 0 To LsLen - 1 LucTotalBytes(LsTotalLen + LiCnt) = LucData(LiCnt) Next '全バイト数 LsTotalLen = LsTotalLen + LsLen Loop Until LNetworkStream.DataAvailable = False サービスだとNetworkStream の DataAvailable では、 終了を正しく判定できないのでしょうか。 何かご存知のことがあれば、ご教授いただければ幸いです。 何度も申し訳ありませんが、よろしくお願い致します。

関連するQ&A

  • バイト配列のバイト数の設定方法を教えてください

    下のようなコードでWebページのソースを取得して、 そのページのコードを解析して、文字化けのない正常な状態で 変数にソースコードを代入するプログラムなのですが、 バイト配列に代入するためのバイト配列の配列数ですが、 5000などとするとページの途中まで正常に取得できるのですが、 多めにと思って50000とかとすると文字化けしてしまいます。 多すぎるとだめなようなのですが、これをぴったりの数値で設定するには ページのバイト数はどのように取得したら良いでしょうか? 下のコードのGetCode(bs)というのは http://dobon.net/vb/dotnet/string/detectcode.html のページにあるコード解析関数の呼び出しの部分です。 Dim txt As String = "http://www.yahoo.co.jp" Dim wc As New System.Net.WebClient Dim fs As System.IO.Stream = wc.OpenRead(txt) Dim bs(5000) As Byte 'byte配列に読み込む fs.Read(bs, 0, bs.Length) fs.Close() '文字コードを取得する Dim enc As System.Text.Encoding = GetCode(bs) 'デコードしてtxtに代入する txt = enc.GetString(bs) よろしくお願いいたします。

  • vb.netのプロパティの使い方について

    こんにちわ! vb.netのプロパティの使い方がわからず困っています。 具体的にはTCPクライアント接続を行い、データ送信前に現在接続を行っているかチェックを行いたいです。 作ったのは↓ Public Class Form1 'ボタンを押したら Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Dim tcp_conect As New System.Net.Sockets.TcpClient 'ソケット作成 Dim net_stream As System.Net.Sockets.NetworkStream = Nothing 'ストリーム取得 Dim send_bytes As Byte() = {&HFF, &H0} '送信データ tcp_conect.Connect("192.168.1.1", "2000") 'ソケット接続 net_stream = tcp_conect.GetStream() 'ソケットストリーム取得 If tcp_conect.conected = True Then 'エラーが出てしまう。 net_stream.Write(send_bytes, 0, send_bytes.Length) 'データ送信 End If tcp_conect.Close() 'ソケット閉じる End Sub End Class 'プロパティ Public Class TcpClient Dim _conect_test As Boolean Public ReadOnly Property Connected As Boolean Get Stop Return _conect_test End Get End Property End Class これでテストをしたいのですが、プロパティが実行されません。 もしかしてプロパティの使い方がそもそも違うのかもしれないのですが、、、 アドバイスのほどよろしくお願いいたします。 ちなみに使用しているのは windows7 Visual Studio Express 2012です。

  • VB2005 で encoding="Shift_JIS"や"EUC-JP"のXMLファイルを保存する方法

    VB2005, XML の初心者です。 VB2005で encoding="Shift_JIS" や "EUC-JP" のXMLデータをファイルに保存するにはどうすれば良いのでしょうか。 encoding="UTF-8"であれば、下記で保存できますが、="Shift_JIS" や "EUC-JP" になると保存でエラーになってしまいます。 下記ソースでは、strXMLには正しくXMLが入っていますが、saveするとエラーになり、ファイルの中身を確認すると、日本語の箇所で切れていました。 Public Client As TcpClient Dim stream As NetworkStream stream = Client.GetStream() Dim Data(10000) As Byte Dim len As Int16 = stream.Read(Data, 0, Data.Length) strXML = System.Text.Encoding.UTF8.GetString(Data, 0, len) MsxmlDoc = New MSXML2.DOMDocument Msxmldoc.Loadxml(strXML) MsxmlDoc.save ( "C:\XML.xml") 文字コードについても初心者ですので、ヒントになるようなことでも教えていただければ幸いです。 よろしくお願い致します。

    • ベストアンサー
    • XML
  • .NET Stringからバイト数を取得する。

    初歩的な質問で申し訳ありません。 Stringから桁数ではなくバイト数を 取得する方法を教えてください。 Dim a As String a = "00あ" とあった場合、 aから4という結果がほしいです。 よろしくお願いします。

  • Sockets.TcpClient プログラミング

    初めて質問するので、作法等に誤りがあるかもしれませんがどうぞよろしくお願いします。 【環境等】 OS:Windows2007 64bit 言語:Visual Stadio 2008 (Framework2.0用で開発)のVB.net 【やりたいこと】 Sockets.TcpClientを使用して自PC上で自PC宛てに通信を行いたい 【解決したい内容】 実行時にファイアウォールのブロック警告をでないようにしたい。 ・初回実行でアクセス許可を行ったあと、アプリを別フォルダに移して実行すると再度警告がでる ・下記自作PGの抜粋 Dim objSck As Sockets.TcpClient Dim objStm As Sockets.NetworkStream Dim myTcpClient As Sockets.TcpClient = myListener.AcceptTcpClient() objSck = myTcpClient objStm = myTcpClient.GetStream() 以上 解決方法をご存じの方はご教示いただければ幸いです。 よろしくお願い致します。

  • vb2008で文字列から文字列コードを取得する方法

    サイトHTMLをWebBrowserを使用せずに取得するために、 Dim stream As System.IO.Stream = client.OpenRead(tbItemURL.Text) Dim reader As New System.IO.StreamReader(stream) Dim strHtml = reader.ReadToEnd() reader.Close() stream.Close() のような形で文字列を取得しています。 しかし、この場合Sift-jis等の場合、後の作業(一部データ取得)で文字化けに悩まされます。 http://dobon.net/vb/dotnet/string/detectcode.html 上記サイトで「バイト配列」に格納して判別する方法があります。 そこで、文字列をバイト配列に格納しようとしますが…。 文字列→バイト配列には文字コードが必要となります。 Dim data() As Byte = Encoding.UTF8.GetBytes(text) なんだか鶏と卵のような感じになってしまいます。 文字列から文字コードを判別する方法はないでしょうか? よろしくお願いします。

  • VB.NETで、20バイト程度のデータを5000件ぐらい一時データとして・・

    VB.NETで、10バイト程度のデータを5000件下手すればもっと?ぐらい一時データとして・・プログラムで使いたいんですが、今はファイルに保存して読み込みながらやってるんですが、処理速度が遅いので、配列にしようかなーと考えているのですが、データベースから読み込んでいるのでデータ数が不明なのです。 dim abc as(10000) as string とかやれば簡単なのですが、これだとメモリ使いすぎ?な気がして。 何かよい方法ないでしょうかー?

  • クラス内に自作のイベントを定義したい VB2005

    VB2005を使っています。 クラス内に自作のイベントを定義したいのですがどうすればよいのでしょうか? 非同期のソケットから帰ってきた場合に発生させるイベントです。 System.Net.Sockets.TcpClient System.Net.Sockets.NetworkStream 以下のようにループでなくイベントで処理させたいです。 Do If .DataAvailable Then             ... End If My.Application.DoEvents() Loop

  • VB6で、指定バイト数を超えた場合はその直前に。

    VB6で、最高文字数を指定するとともに、そのバイト数を超えた場合、超える直前の状態を出力する文字列とする、という処理を考えています。 最大のバイト数を116とすると、全角なら58文字までですが、 57文字まで全角で入力し、次の一文字を半角にする。 そして最後に全角を1文字打つと、116バイトを超えてしまうので、 出力文字は半角のところまでとする。 という形です。 Public Function GetStrForLimitByte(cs As String, size As Long) Dim i As Long Dim p As Long Dim limitStr As String Dim temp As String Dim parts() As String limitStr = "" ' 文字列のバイト数が指定バイト数以下は文字列をそのまま返す If (LenB(cs) <= size) Then cs = cs Else p = Len(cs) For i = 1 To p parts(i) = Mid(cs, i, 1) '1文字ずつ連結 temp = limitStr + parts(i) If (LenB(temp) > size) Then limitStr = limitStr Else limitStr = limitStr + parts(i) End If Next End If End Function すると、parts(i) = Mid(cs, i, 1)のところで「インデックスが有効範囲でありません。」 というメッセが出てしまいます。 なぜでしょうか? ご回答お待ちします、お願いします。

  • データ数の定まらないデータをもれなく配列変数に格納する方法

    あるときは10個またあるときは100個のデータがあるとします。 しかし、データの数は1000個になるかもしれませんし、1個になるかもしれません。 ただし、データ数が0個以下になることはありません。 このような、データ数の定まらないデータを確実にもれなく配列変数に代入したいのですが、方法がわかりません。 変数で dim hairetu(kazu) as integer として配列の数を設定できれば良いのですが、どうも無理のようです。 データの最大数(仮に1000個)を決めて dim hairetu(1000) as integer とするしかないのでしょうか。 何か良い方法はありませんでしょうか。