投稿者 魔界の仮面弁士  (社会人) 投稿日時 2019/10/29 00:47:29
VB6 と VB.NET の文字列型には、大きな違いがひとつあります。

VB6 の String 型は、「任意のバイナリデータ」を格納できるようになっています。
既定では UTF-16 でエンコードされたバイナリが入っていますが、実際にはそれ以外、
たとえば Shift_JIS でエンコードされたバイナリを格納することもできますし、やろうと思えば
exe ファイルのバイナリデータを蓄えさせることだって可能です。

それに対し、VB.NET の String は、常に UTF-16 相当で符号化されたデータしか保持できません。
故に、文字列型変数に Shift_JIS エンコードのデータを格納することは、原理的に不可能です。

-------

さて。今回提示頂いた VB6 の
 Len(StrConv(MidB(文字列型変数, 20, 2), vbUnicode))
というコードが返しうる値は、「Null」「0」「1」「2」のいずれかです。

もしも『文字列型変数』の部分が As Variant ではなく As String の場合は、
「0」「1」「2」のいずれかになるでしょう。この点の認識は相違ないでしょうか?

-------

上記処理においては、「文字列型変数」に入っている値は
「Shift_JIS でエンコードされたバイナリデータ」であることが期待されます。

そして、MidB 関数によって、そのバイナリデータから、
「19 バイト目から20バイト目」にあたる 2 バイト分を切り出しています。
※先頭を 0 バイト目としてカウントした場合。

そしてそれを、StrConv(, vbUnicode) によって、符号化方式を Shift_JIS から UTF-16 へと
変換してデコードすることで「文字列」として取り出し、最後にそれを Len 関数で
文字数を取得するという流れです。

もし、MidB での切り出す位置が悪く、Shift_JIS の全角文字が分断されるようなことがあれば、
その後の StrConv での vbUnicode 変換は文字化けすることになります。

-------

話を VB.NET に移しましょう。

冒頭で述べた通り、VB.NET の String 型には、
「Shift_JIS でエンコードされたバイナリデータ」を格納することができません。
VB.NET において、String 型で受け取れるのは Unicode 文字列のみです。

ですから、そもそも最初のデータの入り口は
 Dim strData As String = Shift_JIS でエンコードされたバイナリデータ
ではなく、
 Dim binData() As Byte = Shift_JIS でエンコードされたバイナリデータ
でなければなりません。


そうすると、その後の MidB(**, 20, 2) に相当する処理というのは、
binData(19)~binData(20) の位置を切り出す処理であるといえます。
切り出すためのコードはいろいろな書き方がありますが、たとえば
  Dim binary(1) As Byte
  Array.Copy(binData, 19, binary, 0, 2)
あるいは、
  Dim binary() As Byte = binData.Skip(19).Take(2).ToArray()
などと書けます。

これで、Shift_JIS バイナリから 2 バイト分を切り出せたので、あとはそれが
Shift_JIS として見た場合の何文字分であるかを調べるだけです。
これには、
  Dim length As Integer = System.Text.Encoding.Default.GetCharCount(binary)
というコードを使います。GetCharCount は文字通り「文字数」を数えるメソッドです。

上記の System.Text.Encoding.Default は、日本語環境では「Shift_JIS 符号化」を表しています。
あるいは System.Text.Encoding.Default の代わりに、
System.Text.Encoding.GetEncoding(932) もしくは
System.Text.Encoding.GetEncoding("Shift_JIS") と書くこともできます。

他言語版の Windows で動かした場合にも Shift_JIS で処理されることを保証したいなら、
Default ではなく GetEncoding で指定した方が良いでしょう。