[2020/03/25] 数値データを指定書式で文字列に変換する(ToString , String.Format) (No.157)
[2019/12/09] TCP (TcpListener, TcpClient)を使ったプロセス間通信について・その2 (No.146)
[2019/12/07] TCP (TcpListener, TcpClient)を使ったプロセス間通信について (No.145)
[2019/11/25] 文字列定数(改行、タブ、バックスペース等)について (No.143)
-
『星野源と松重豊のおともだち』の2026年1月7日放送にて、なんと懐かしのKalapana(カラパナ)を聞いた。
2026年1月7日放送回にてオンエアされた楽曲特集の中に先頭にかかった曲が「Kalapana」の「Real Thing」でした。
「Kalapana」といえば、70年代~80年代にかけて サーフロック とか言われていたことを思い出しました。
いやー本当に懐かしい、当時20歳代前後だったので結構おぼえています。 こんなことを言うと、現在の年齢がばれますが、高齢者の範疇です。
年寄りでもロックなどを聴くのかと言われるかもしれませんが、聞くんですよ。 自分が若い頃に聴いていた曲を中心ですが…
若い頃(青春時代)頃の曲を聴くと、精神的に良いそうです。 確かに自分のテンションが上がるのがわかります。
テレビで懐かしのメロディー的な番組があるのがわかります。
「Kalapana」の「Real Thing」
リンク「Real Thing」について
さて「Real Thing」ですがこの曲はかのボビー・コールドウェルの曲(1989年)なんですね。
このボビー・コールドウェルは私のお気に入りのミュージシャン(最近はアーティストというそうですが、[airtist:芸術家]の本来の意味との違和感から)で 80年代は「イブニング・スキャンダル(日本での名前?)」からの結構なファンです。
メロウな感じで夏の暑い日にベッドに横たわって聴いていると、まったりできます、本当に懐かしい。
リンクあとがき
この記事を書いている時点は、昨日(1月14日)の韓国編の放送を視聴した後です。
昨日の放送でも、最後の荒井由実さんの「陰りゆく部屋」は本当に良かったです。 自分もCDを持っているので、たまには聴くのですが、テレビから流れてくる感じの最初のパイプオルガンには感動しました。
この番組ですが、今後も注目していきたいと思います。
PR -
数値データを表示するために各種の書式の文字列に変換することはよくあります。 各データ型が持つ ToString メソッドを使えば以下の様な感じでできます。
Console.WriteLine((12345).ToString("C")) '¥12,345 と表示 Console.WriteLine((12345).ToString("D8")) '00012345 と表示 Console.WriteLine((1234.567).ToString("00000.00")) '01234.57 と表示
上の (12345) の部分は文字列 "12345" を Integer型 データとして変換されます。 また (1234.567) の部分は文字列 "1234.567" を Double型 データとして変換され、それぞれの ToString メソッドが呼ばれます。
ToString メソッドの引数の文字列には各種存在し、 「標準の数値書式指定文字列」と「カスタム数値書式指定文字列」の2種類があります ので、順を追って説明します。■「標準の数値書式指定文字列」について
次の表に、標準の数値書式指定文字列の説明および書式指定子ごとのサンプル出力を示します。書式指定子 名称 対象データ型 結果 精度指定子 サンプル "C" or
"c"通貨型 全ての数値型 通貨値 小数部の桁数 (123.456).ToString("C") = ¥123
(-123.456).ToString("C3") = -¥123.456"D" or
"d"Decimal 整数型のみ 必要に応じて
負の符号が付く整数と小数最小桁数 (1234).ToString("D") = 1234
(-1234).ToString("D6") = -001234"E" or
"e"指数 全ての数値型 指数表記 小数部の桁数 (123.456).ToString("E") = 1.234560E+002
(0.12345).ToString("e3") = 1.235e-001"F" or
"f"固定小数点 全ての数値型 必要に応じて
負の符号が付く整数と小数小数部の桁数 (1234.567).ToString("F") = 1234.57
(1234).ToString("F1") = 1234.0
(-1234.56).ToString("F3") = -1234.560"G" or
"g"全般 全ての数値型 固定小数点表記or
指数表記の何れか簡潔な形式有効桁数 (-123.456).ToString("G") = -123.456
(123.4546).ToString("G4") = 123.5
(-1.23456E-25).ToString("G") = -1.23456E-25"P" or
"p"パーセント 全ての数値型 数値に 100 を掛けて
%記号を付けて表示小数部の桁数 (1).ToString("P") = 100.00 %
(-0.39678).ToString("P1") = -39.7 %"X" or
"x"16進数 整数型のみ 16進数文字列 結果文字列の桁数 (255).ToString("X") = FF
(-1).ToString("X") = FFFFFFFF
(255).ToString("x4") = 00ff
(1000).ToString("X4") = 03E8
書式指定子は上記の様にたくさんありますが、実際に使ったものとなると "C" と "D" ぐらいです。 指数表記は科学計算で必要になるぐらいで、私はあまり使った記憶がありません。
尚、以下のソースで簡単な例を示します。Private Sub btnTest_Click(sender As Object, e As EventArgs) Handles btnTest.Click '「Double」型データ Dim dbTest As Double = 0.0 '「Long」型データ Dim lngTest As Long = 0 '標準の数値書式指定文字列「C,c」 Console.WriteLine("標準の数値書式指定文字列「C,c」") dbTest = 123 Console.WriteLine(dbTest.ToString("C")) dbTest = 123.56 Console.WriteLine(dbTest.ToString("C")) dbTest = 123.456 Console.WriteLine(dbTest.ToString("C2")) dbTest = -123.56 Console.WriteLine(dbTest.ToString("C")) '標準の数値書式指定文字列「D,d」 Console.WriteLine("標準の数値書式指定文字列「D,d」") lngTest = 123 Console.WriteLine(lngTest.ToString("D")) Console.WriteLine(lngTest.ToString("D5")) lngTest = -123 Console.WriteLine(lngTest.ToString("D6")) End Sub実行結果がコンソールには以下様に表示されます。
標準の数値書式指定文字列「C,c」 \123 \124 \123.46 -\124 標準の数値書式指定文字列「D,d」 123 00123 -000123
■「カスタム数値書式指定文字列」について
次の表に、カスタム数値書式指定文字列の説明および書式指定子ごとのサンプル出力を示します。 (よく使うものをピックアップしてあります)書式指定子 名称 説明 サンプル "0" ゼロ
プレース
ホルダー対応する数字でゼロを置き換えます。
置き換えが行われるのは対応する数字が存在する場合です。
それ以外の場合は結果の文字列にはゼロが表示されます。(1234).ToString("00000") = "01234"
(-1.23).ToString("000.000") = "-001.230"
(123.456).ToString("00.00") = "123.46""#" 桁
プレース
ホルダー対応する数字で "#" 記号を置き換えます。
置き換えが行われるのは対応する数字が存在する場合です。
それ以外の場合は結果の文字列に数字は表示されません。(1234).ToString("00000") = "01234"
(-1.23).ToString("000.000") = "-001.230"
(123.456).ToString("00.00") = "123.46""." 小数点 結果の文字列の小数点位置を決定します。 (123.45).ToString("0.0") = "123.5"
(-1.2).ToString("00.00") = "-01.20""," 桁区切り
数値位取り(0 または #) の間に1つ以上の "," が在る場合は
桁区切り記号が挿入。
数値位取りとしては
指定された "," ごとに数値を 1000 で除算します。(123456).ToString("#,0") = "123,456"
(1678).ToString("0,") = "2"
(123456789).ToString("0,,") = "123"";" セクション
区切り正、負、ゼロの数値に対して
別々の書式指定文字列でセクションを定義します。
2セクション:
・最初のセクションが正の値とゼロに適用
・2番目のセクションが負の値に適用
3セクション:
・最初のセクションが正の値に適用
・2番目のセクションが負の値に適用
・3番目のセクションがゼロに適用(12.345).ToString("#0.0#;(#0.0#);-\0-") = "12.35"
(0).ToString("#0.0#;(#0.0#);-\0-") = "-0-"
(-12.345).ToString("#0.0#;(#0.0#);-\0-") = "(12.35)""%" パーセント
プレース
ホルダー数値に 100 を乗算し結果の文字列に
パーセント記号を挿入します。(0.3697).ToString("%#0.00") = %36.97 '文字列' リテラル
文字列
区切り囲まれた文字列が結果の文字列に
そのまま出力される。(0.3697).ToString("'P:'%#0.00") = P:%36.97
尚、上記の例を以下のソースで示します。Private Sub btnTest_Click(sender As Object, e As EventArgs) Handles btnTest.Click '「Double」型データ Dim dbTest As Double 'カスタム数値書式指定文字列["0"] Console.WriteLine("カスタム数値書式指定文字列[""0""]") dbTest = 123 Console.WriteLine(dbTest.ToString("00000")) dbTest = 123.456 Console.WriteLine(dbTest.ToString("00000.00")) dbTest = -123.56 Console.WriteLine(dbTest.ToString("00000.00")) 'カスタム数値書式指定文字列["#"] Console.WriteLine("カスタム数値書式指定文字列[""#""]") dbTest = 123 Console.WriteLine(dbTest.ToString("#####")) dbTest = 123.456 Console.WriteLine(dbTest.ToString("#####.##")) dbTest = -123.56 Console.WriteLine(dbTest.ToString("#####.##")) 'カスタム数値書式指定文字列[";"] Console.WriteLine("カスタム数値書式指定文字列["";""]") dbTest = 123 Console.WriteLine(dbTest.ToString("#####;[#####];'ZERO'")) dbTest = 0 Console.WriteLine(dbTest.ToString("#####;[#####];'ZERO'")) dbTest = -123.56 Console.WriteLine(dbTest.ToString("#####.##;[#####.##];'ZERO'")) '最後に複合的な使い方 Console.WriteLine("最後に複合的な使い方") dbTest = 12345678.123 Console.WriteLine(dbTest.ToString("'テストデータ:'#,0.00")) End Sub実行結果がコンソールには以下様に表示されます。
セクション区切りを使用して1個の書式文字列で、正、負、ゼロで別々の書式が指定できますので、 数値を判断して個別に処理を分けなくてもよくなります。
カスタム数値書式指定文字列["0"] 00123 00123.46 -00123.56 カスタム数値書式指定文字列["#"] 123 123.46 -123.56 カスタム数値書式指定文字列[";"] 123 ZERO [123.56] 最後に複合的な使い方 テストデータ:12,345,678.12
■「複合書式指定文字列」について
複合書式指定文字列とは、出力される固定文字列の中に挿入されるべきデータ用のプレースホルダーを記入したものです。 このプレースホルダーはインデックス化されていて、「0」から順に番号が振られます。
この複合書式指定文字列を引数として使えるメソッドに String.Format や Console.WriteLine などがあります。 複合書式指定文字列の引数の後ろに、プレースホルダーに対応する出力したいデータを記述します。
この説明ではよく分からないので、以下の例を見てください。
{ } で囲まれた数字がインデックスで、対応するデータの引数の位置を示しているのが分かります。Private Sub btnTest_Click(sender As Object, e As EventArgs) Handles btnTest.Click Dim intData As Integer = 10 Dim lngData As Long = 1000 Dim dblData As Double = 123.45 Console.WriteLine("Integer:{0}, Long:{1}, Double:{2}", intData, lngData, dblData) End Sub実行結果がコンソールには以下様に表示されます。
Integer:10, Long:1000, Double:123.45
尚、プレースホルダーの書式は以下の様になっています。
<プレースホルダー書式> { index [,alignment] [:formatString] } ・index:パラメーター指定子とも呼ばれ、 オブジェクトのリスト内で対応する項目を識別するための 0 から始まる数値です。 ・[,alignment]:書式設定フィールドの幅を指定する符号付き整数です。 フィールド内の書式設定されたデータは、alignment が正の場合は右揃え、 alignment が負の場合は左揃えされます。 埋め込みが必要な場合は、空白が使用されます。 ・[:formatString]:書式設定されるオブジェクトの種類に適した書式指定文字列です。 「標準の数値書式指定文字列」「カスタム数値形式文字列」が指定できます。
プレースホルダーの書式にいろいろ付け加えて、上記のソースを以下の様にしました。Private Sub btnTest_Click(sender As Object, e As EventArgs) Handles btnTest.Click Dim intData As Integer = 10 Dim lngData As Long = 1000 Dim dblData As Double = 123.45 Console.WriteLine("Integer:{0,7:0.00}, Long:{1,-6:#,0}, Double:{2,10:###0.000}", _ intData, lngData, dblData) End Sub実行結果がコンソールには以下様に表示されます。
Integer: 10.00, Long:1,000 , Double: 123.450
関連する記事
⇒指定した精度の桁数に数値を切り上げ :[Math.Ceiling,Math.Floor]
⇒文字列から数値型への変換(parse - tryparse)
⇒オブジェクト型から数値型への変換(TryParse)
-
前回の TCP の記事では、クライアント側で1回の通信毎に TCP の接続を切断していたので、 複数回の文字列送信ができませんでした。
それで今回は、クライアント側で TCP の接続のタイミングと、文字列送信のタイミングを別々で行う様にすることで 複数回の文字列送信を可能にしています。
これを行う為に、以下のクライアント側の処理手順の中で、(1)(2)を1個の処理として、また(5)の処理も別のタイミングに追い出します。 具体的にはそれぞれフォームにボタンを設置(「Start」「Stop」の名前で)し、それぞれのクリック処理内でそれらを行います。- (1)IP アドレスとポート番号で TcpClient クラスの生成によりTCPソケット作成・接続
- (2)TcpClient クラスの GetStream メソッドで NetworkStream を取得
- (3)NetworkStream の Write メソッドでテキストボックスの内容をバイト配列化して送信
- (4)NetworkStream の Read メソッドでサーバからの応答を受信しテキストボックスに表示
- (5)最後にネットワークストリーム、ソケットをクローズ
それでは以下にクライアント側のソースを示します。 TcpClient と NetworkStream クラスのオブジェクトを関数の外に出し、静的変数としています。
■TCP クライアント側のプログラム
Imports System.Net Imports System.Text Public Class frmTcpClient 'サーバーのIPアドレス(または、ホスト名)とポート番号 Dim strIpAddr As String = "localhost" Dim intPort As Integer = 60000 'ソケット Dim mTcpClient As Sockets.TcpClient 'ソケットストリーム Dim mNetStream As Sockets.NetworkStream '[Start]リック時イベント Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click 'ソケット生成 mTcpClient = New Sockets.TcpClient 'ソケット接続 mTcpClient.Connect(strIpAddr, intPort) 'ソケットストリーム取得 mNetStream = mTcpClient.GetStream() End Sub '[Stop]リック時イベント Private Sub btnStop_Click(sender As Object, e As EventArgs) Handles btnStop.Click 'ソケットクローズ mNetStream.Close() mTcpClient.Close() End Sub '[Send]リック時イベント Private Sub btnSend_Click(sender As Object, e As EventArgs) Handles btnSend.Click Try '送信文字列をバイト配列変換 Dim enc As Encoding = Encoding.GetEncoding("SHIFT-JIS") '最後尾にCR Dim data As Byte() = enc.GetBytes(Me.TextBox1.Text.Trim & ControlChars.Cr) Me.TextBox1.Text = "" 'ソケット送信 mNetStream.Write(data, 0, data.Count) 'サーバからの応答を受信 Dim bytRead As Byte() = New Byte(255) {} Dim intBytes As Integer = mNetStream.Read(bytRead, 0, bytRead.Length) '受信したデータを文字列に変換 Dim resMsg As String = enc.GetString(bytRead, 0, intBytes) '末尾の\rを削除し表示 Me.TextBox2.Text = resMsg.TrimEnd(ControlChars.Cr) Catch ex As Exception MsgBox(ex.Message) End Try End Sub End Classサーバ側のプログラムに変更は無いのですが、一応ソースを載せておきます。
■TCP サーバ側のプログラム
Imports System.Net Imports System.Threading Imports System.Text Public Class frmTcpServer 'リッチテキストボックスにメッセージを表示する Public Sub DispMsg(ByVal message As String) RichTextBox1.AppendText(message & vbNewLine) RichTextBox1.SelectionStart = RichTextBox1.TextLength RichTextBox1.Refresh() End Sub '[Start]ボタンクリック Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click 'ボタン制御 Me.btnStart.Enabled = False 'ポート番号 Dim pintPort As Integer = 60000 'IPアドレス&ポート番号設定 Dim pEndPoint As New IPEndPoint(IPAddress.Any, pintPort) 'ソケット・リスナー作成 Dim pListener As New Sockets.TcpListener(pEndPoint) 'リスナー開始 pListener.Start() Call DispMsg("リスナー開始...") 'クライアントから接続有りでこの処理を抜ける Dim pTcpClient As Sockets.TcpClient = pListener.AcceptTcpClient() Call DispMsg("クライアントから接続有り...") '送受信用ソケットストリーム取得 Dim pNetStream As Sockets.NetworkStream = pTcpClient.GetStream() 'バイト配列(取敢えず受信バッファとして256バイト) Dim bytRead As Byte() = New Byte(255) {} 'ソケット受送信ループ While True 'TCP受信(バッファ領域まで) Dim intBytes As Integer = pNetStream.Read(bytRead, 0, bytRead.Count) If intBytes = 0 Then Exit While End If '受信したデータを文字列に変換 Dim enc As Encoding = Encoding.GetEncoding("SHIFT-JIS") Dim resMsg As String = enc.GetString(bytRead, 0, intBytes) '末尾の\rを削除 resMsg = resMsg.TrimEnd(ControlChars.Cr) '表示 Call DispMsg(resMsg) '正常受信の場合、送信データ作成 Dim bytSend() As Byte = enc.GetBytes(resMsg & "...ACK" & ControlChars.Cr) 'ソケット送信 pNetStream.Write(bytSend, 0, bytSend.Length) End While 'ソケットストリームクローズ pNetStream.Close() 'クライアントクローズ pTcpClient.Close() 'リスナー停止 pListener.Stop() Call DispMsg("リスナー停止...") 'ボタン制御 Me.btnStart.Enabled = True End Sub End Class実際の実行は以下の様になります。
サーバ側の「Start」押下後、クライアント側の「Start」を押下し”abcdef”,”123456”,”ABCDEFGHI”の順に文字列を「Send」し、 更に「Stop」を押下したところまでを表しています。
ここまでのPGはサーバとクライアントが1対1のみでしか動作しません。 しかし、これでは面白くありませんので、次回は複数のクライアントからの接続を受け付けるものを紹介したいと思います。関連する記事
⇒TCP (TcpListener, TcpClient)を使ったプロセス間通信について
⇒Remoting の IPC を使ったプロセス間通信について
⇒Remoting の IPC を使ったプロセス間通信についてその2(HTTPチャネル)
⇒名前付きパイプを使ったプロセス間通信について
⇒名前付きパイプを使ったプロセス間通信についてその2(複数クライアントとの通信)
⇒名前付きパイプを使ったプロセス間通信についてその3(クライアントとの双方向通信)
-
このページでは TCP を使ったプロセス(EXE)間で通信について説明します。 (いわゆる TCP クライアント・サーバプログラム を作ることになります。)
TCP クライアントは TcpClient クラスを、 TCP サーバは TcpListener クラスを使います。
そこで先ずは TCP サーバのプログラムの例を示します。 今回の処理は TCP での受信待ち状態にし、クライアントからの1回のメッセージを受信し、 そのメッセージをクライアント側に返し、処理が終わるという簡単なものです。 以下にその手順を示します。- IP アドレスとポート番号でネットワークエンドポイントを作成し TcpListener クラスの生成
- TcpListener クラスの Start メソッドで受信接続要求の待機を開始
- TcpListener クラスの AcceptTcpClient メソッドでクライアントからの接続要求を待機
- 接続要求待機を抜けた後で送受信用ソケットストリーム取得
- ソケットストリームからデータ受信し、さらにデータを送信
- 最後にソケットストリーム等をクローズし、リスナーを停止
以下にそのソースを示します。 フォーム上にはサーバ開始用の「start」ボタンと、送受信文字列等を表示する為に RichTextBox を設置しています。
■TCP サーバープログラム
Imports System.Net Imports System.Threading Imports System.Text Public Class frmTcpServer 'リッチテキストボックスにメッセージを表示する Public Sub DispMsg(ByVal message As String) RichTextBox1.AppendText(message & vbNewLine) RichTextBox1.SelectionStart = RichTextBox1.TextLength RichTextBox1.Refresh() End Sub '[Start]ボタンクリック Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click 'ボタン制御 Me.btnStart.Enabled = False 'ポート番号 Dim pintPort As Integer = 60000 'IPアドレス&ポート番号設定 Dim pEndPoint As New IPEndPoint(IPAddress.Any, pintPort) 'ソケット・リスナー作成 Dim pListener As New Sockets.TcpListener(pEndPoint) 'リスナー開始 pListener.Start() Call DispMsg("リスナー開始...") 'クライアントから接続有りでこの処理を抜ける Dim pTcpClient As Sockets.TcpClient = pListener.AcceptTcpClient() Call DispMsg("クライアントから接続有り...") '送受信用ソケットストリーム取得 Dim pNetStream As Sockets.NetworkStream = pTcpClient.GetStream() 'バイト配列(取敢えず受信バッファとして256バイト) Dim bytRead As Byte() = New Byte(255) {} 'ソケット受送信ループ While True 'TCP受信(バッファ領域まで) Dim intBytes As Integer = pNetStream.Read(bytRead, 0, bytRead.Count) If intBytes = 0 Then Exit While End If '受信したデータを文字列に変換 Dim enc As Encoding = Encoding.GetEncoding("SHIFT-JIS") Dim resMsg As String = enc.GetString(bytRead, 0, intBytes) '末尾の\rを削除 resMsg = resMsg.TrimEnd(ControlChars.Cr) '表示 Call DispMsg(resMsg) '正常受信の場合、送信データ作成 Dim bytSend() As Byte = enc.GetBytes(resMsg & "...ACK" & ControlChars.Cr) 'ソケット送信 pNetStream.Write(bytSend, 0, bytSend.Length) End While 'ソケットストリームクローズ pNetStream.Close() 'クライアントクローズ pTcpClient.Close() 'リスナー停止 pListener.Stop() Call DispMsg("リスナー停止...") 'ボタン制御 Me.btnStart.Enabled = True End Sub End Class以下に TCP クライアントのプログラムの例を示します。 この処理は、TCPソケットを作成・接続した後で、NetworkStream によりサーバへデータを送信し、 その後サーバからの応答を受信します。
- IP アドレスとポート番号で TcpClient クラスの生成によりTCPソケット作成・接続
- TcpClient クラスの GetStream メソッドで NetworkStream を取得
- NetworkStream の Write メソッドでテキストボックスの内容をバイト配列化して送信
- NetworkStream の Read メソッドでサーバからの応答を受信しテキストボックスに表示
- 最後にネットワークストリーム、ソケットをクローズ
以下にそのソースを示します。 フォーム上には送信文字列用と受信文字列用のテキストボックス、送信開始用の「Send」ボタンを設置しています。
■TCP クライアントプログラム
Imports System.Net Imports System.Text Public Class frmTcpClient '[Send]リック時イベント Private Sub btnSend_Click(sender As Object, e As EventArgs) Handles btnSend.Click Me.btnSend.Enabled = False Try 'サーバーのIPアドレス(または、ホスト名)とポート番号 Dim strIpAddr As String = "localhost" Dim intPort As Integer = 60000 'ソケット生成・指定したホストの指定したポートに接続 Dim pTcpClient = New Sockets.TcpClient(strIpAddr, intPort) 'ソケットストリーム取得 Dim pNetStream As Sockets.NetworkStream = pTcpClient.GetStream() '送信文字列をバイト配列変換 Dim enc As Encoding = Encoding.GetEncoding("SHIFT-JIS") '最後尾にCR Dim data As Byte() = enc.GetBytes(Me.TextBox1.Text.Trim & ControlChars.Cr) Me.TextBox1.Text = "" 'ソケット送信 pNetStream.Write(data, 0, data.Count) 'サーバからの応答を受信 Dim bytRead As Byte() = New Byte(255) {} Dim intBytes As Integer = pNetStream.Read(bytRead, 0, bytRead.Length) '受信したデータを文字列に変換 Dim resMsg As String = enc.GetString(bytRead, 0, intBytes) '末尾の\rを削除し表示 Me.TextBox2.Text = resMsg.TrimEnd(ControlChars.Cr) 'ソケットクローズ pNetStream.Close() pTcpClient.Close() Catch ex As Exception MsgBox(ex.Message) End Try Me.btnSend.Enabled = True End Sub End Class実際の実行は以下の様になります。
今回のPGはクライアント側で文字列送信後すぐに接続を切っていますので、 1回の送受信毎にサーバ側で「start」をクリックしないといけないので実用には供しないですが、ご参考になればと思います。
次回はこれを踏まえて、サーバ側で開始したらそのまま連続でクライアントからの受信と送信を出来る様にしたいと思います。関連する記事
⇒TCP (TcpListener, TcpClient)を使ったプロセス間通信について・その2
⇒Remoting の IPC を使ったプロセス間通信について
⇒Remoting の IPC を使ったプロセス間通信についてその2(HTTPチャネル)
⇒名前付きパイプを使ったプロセス間通信について
⇒名前付きパイプを使ったプロセス間通信についてその2(複数クライアントとの通信)
⇒名前付きパイプを使ったプロセス間通信についてその3(クライアントとの双方向通信)
-
文字列の一種として、特殊文字の「改行」「タブ」「バックスペース」等をシステム定数として定義されています。
この定義済みの文字列を紹介します。 特殊文字として使うとすれば「復帰」「ラインフィード」「改行」「タブ」「バックスペース」ぐらいでしょうか。
以下の様にシステム定数文字列 vbCr , vbLf , vbNewLine , vbTab , vbBack を使います。 長さが1(復帰のみ2)の文字列として文字列変数にそのまま代入したり連結する形で使えます。 (これらの文字列は Microsoft.VisualBasic.Constants モジュールに定義されています。)
また Microsoft.VisualBasic.ControlChars モジュールにも同じものが定義されていますので、こちらを使うこともできます。
ところで1つはまる点があるのですが、 C# や PHP などではダブルクォテーションで文字列を定義した時に 「¥」円マーク(バックスラッシュ)でエスケープ文字として特殊文字を記述できるので VB.NET でも同じ様に記述すると 単なる「¥」と「n」等の文字そのものになります。■定義済みの文字列定数
Dim str1 As String Dim str2 As String Dim str3 As String '復帰文字 : &H0D str1 = vbCr str2 = ControlChars.Cr str3 = "\r" 'VB.NET では \ はそのままの文字列でエスケープシーケンスではない! Console.WriteLine("vbCr = ControlChars.Cr : " & (str1 = str2) & _ " ControlChars.Cr = ""\r"" : " & (str2 = str3)) 'ラインフィード文字 : &H0A str1 = vbLf str2 = ControlChars.Lf str3 = "\n" Console.WriteLine("vbLf = ControlChars.Lf : " & (str1 = str2) & _ " ControlChars.Lf = ""\n"" : " & (str2 = str3)) '復帰文字とラインフィード文字の組み合わせ : &H0D &H0A str1 = vbCrLf str2 = ControlChars.CrLf str3 = "\r\n" Console.WriteLine("vbCrLf = ControlChars.CrLf : " & (str1 = str2) & _ " ControlChars.CrLf = ""\r\n"" : " & (str2 = str3)) '改行文字(WindowsではvbCrLfと同等) str1 = vbNewLine str2 = ControlChars.NewLine str3 = "\n" Console.WriteLine("vbNewLine = ControlChars.NewLine : " & (str1 = str2) & _ " ControlChars.NewLine = ""\n"" : " & (str2 = str3)) 'タブ文字 : &H9 str1 = vbTab str2 = ControlChars.Tab str3 = "\t" Console.WriteLine("vbTab = ControlChars.Tab : " & (str1 = str2) & _ " ControlChars.Tab = ""\t"" : " & (str2 = str3)) 'バックスペース文字 : &H8 str1 = vbBack str2 = ControlChars.Back str3 = "\t" Console.WriteLine("vbBack = ControlChars.Back : " & (str1 = str2) & _ " ControlChars.Back = ""\b"" : " & (str2 = str3))上記のソースの部分のみを実行させた場合に、デバッグ出力ウインドウに以下の様に表示されました。
vbCr = ControlChars.Cr : True ControlChars.Cr = "\r" : False vbLf = ControlChars.Lf : True ControlChars.Lf = "\n" : False vbCrLf = ControlChars.CrLf : True ControlChars.CrLf = "\r\n" : False vbNewLine = ControlChars.NewLine : True ControlChars.NewLine = "\n" : False vbTab = ControlChars.Tab : True ControlChars.Tab = "\t" : False vbBack = ControlChars.Back : True ControlChars.Back = "\b" : False
当然なのですが結果から vbCr と ControlChars.Cr は同じであることがわかります。 (他の文字列も同様です)
■定義済みの文字列定数を使う場面について
上記の定義済みの文字列定数を使えば改行等がソース上に視覚的にはっきりとわかる形で記述できます。
ではどの様な時にこれを使う意味が有るのか。 私の場合、改行文字が必要な場面と言えば、 Oracle 等のデータベースへの SQL 文を作成する場合に使用します。 以下のソースでその例をしめします。生成される SQL 文は例なので意味はありません。'接続文字列(これ自身は意味がありません) Dim strConnect As String = "Data Source=//*********/test; User ID=test;Password=test;" 'オラクル接続オブジェクト Dim Conn As New OracleConnection(strConnect) 'オラクル接続オープン Conn.Open() 'SQL文 Dim strSQL As String = "" strSQL &= "SELECT " & vbCrLf strSQL &= " TT.伝票番号, TT.伝票日付" & vbCrLf strSQL &= "FROM 売上伝票 TT" & vbCrLf strSQL &= "WHERE TT.伝票日付 = TO_DATE('2019/11/12')" & vbCrLf strSQL &= "ORDER BY TT.伝票番号" & vbCrLf 'コマンドオブジェクト(SQL文と接続オブジェクト) Dim Cmd As New OracleCommand(SQL, Conn) Cmd.CommandType = CommandType.Text '読込オブジェクトに接続 Dim dr As OracleDataReader = Cmd.ExecuteReader() '*** この後はデータ処理... ***このソースでは SQL 文を SELECT FROM WHERE ORDER BY の各句で改行を入れています。
この改行ですが Oracle SQL 文の解析を行う時に空白文字の様にホワイトスペースとして扱われ、文字列の中では単語の区切りとみなされます。 そのため、この SQL 文では句の区切りとして使用しています。
改行を入れなくても、先頭に1文字空白を入れれば同じことにはなるのですが、テキストとして見ると改行が入った方が見やすい為です。 (先頭に空白を入れ忘れた時のバカ除けでもあります)
実際システムではよく実行 SQL 文のログを残したりしますが、 その時に長い文字列の1行よりも適当に改行が入っていた方が見やすいのです。
■ダブルクォテーションそのものを文字列の中に定義する方法
ダブルクォテーションそのものを文字列の中に宣言したい場合について説明します。 文字列はダブルクォテーションで囲まれていますが、その文字列の中でダブルクォテーションを2回連続して記述します。 (""として記述)
文字列の中にダブルクォテーションを記述する例として思い当たるのは、 上記のソースの SQL 文の中でカラム名とテーブル名が全角になっていますが、 Oracleではこれらをダブルクォテーションで 囲んだ方が安全です。(昔の Oracle ではある全角文字がうまく判定できないことがありました。)
結果として以下の様な記述になります。'SQL文 Dim strSQL As String = "" strSQL &= "SELECT " & vbCrLf strSQL &= " TT.""伝票番号"", TT.""伝票日付""" & vbCrLf strSQL &= "FROM ""売上伝票"" TT" & vbCrLf strSQL &= "WHERE TT.""伝票日付"" = TO_DATE('2019/11/12')" & vbCrLf strSQL &= "ORDER BY TT.""伝票番号""" & vbCrLf