C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[6]: JISコード⇒シフトJISコードに変換し形式をHEX


(過去ログ 63 を表示中)

[トピック内 9 記事 (1 - 9 表示)]  << 0 >>

■36576 / inTopicNo.1)  JISコード⇒シフトJISコードに変換し形式をHEX
  
□投稿者/ ooo (35回)-(2009/06/02(Tue) 10:17:11)

分類:[VB6 以前] 

お世話になります。

以下はVB6にてシフトJISコードからJISコードへ変換を行い変換後の形式をHEXおよびバイナリに変換する関数となります。
皆様にお聞きしたいのは以下の逆でJISコード⇒シフトJISコードに変換し形式をHEXにするにはどうすればよいでしょうか?
どなたか、教示いただけたら幸いです。

'***************************************************************************************************
'------------------------
'FUNCTION情報
'------------------------
'FUN名  :Kanji_Conv
'処理概要    :変換処理
'              漢字文字をJISに変換する
'引数1    :psPara       IN  変換形式
'引数2    :psSiftJis    IN  変換対象値
'
'戻り値      :変換後JISコード
'***************************************************************************************************
Public Function Kanji_Conv(psPara As String, psSiftJis As String) As String
Rem シフトJISコードからJISコードへ変換
'   psPara      :   H=HEX   B=Binary
'   psSiftJis   :   シフトJISコード

    Dim i As Integer                                '桁数のリターンコード
    Dim vConv                                       'ワーク変数
    Dim vHex                                        '4バイトのシフトJISコードに変換のリターンコード
    Dim vUpByte                                     '上位2バイトを1バイトに変換のリターンコード
    Dim vDownByte                                   '下位2バイトを1バイトに変換のリターンコード
    
    vConv = ""                                      'ワーク変数の初期化
    For i = 1 To Len(psSiftJis)                     '桁数分繰り返す
        vHex = Hex(Asc(Mid$(psSiftJis, i, 1)))      '4バイトのシフトJISコードに変換
        If vHex = "20" Then
           Exit For
        End If
        vUpByte = Val("&h" + Mid$(vHex, 1, 2))      '上位2バイトを1バイトに変換
        vDownByte = Val("&h" + Mid$(vHex, 3, 2))    '下位2バイトを1バイトに変換
        If vUpByte >= &HE0 Then                     '上位1バイトがE0hの場合の処理
           vUpByte = vUpByte - &H40
        End If
        vUpByte = (vUpByte - &H81) * 2 + &H21
        If vDownByte > &H7F Then                    '下位1バイトが80h以上の処理
           vDownByte = vDownByte - 1
        End If
        If vDownByte > &H9D Then                    '下位1バイトが9Eh以上の処理
           vUpByte = vUpByte + 1
           vDownByte = vDownByte - (&H9E - &H21)
        Else
           vDownByte = vDownByte - (&H40 - &H21)    '下位1バイトが9D以下の処理
        End If
        
        Select Case psPara
               Case "H"
                    vConv = vConv + Hex(vUpByte) + Hex(vDownByte)    'ワーク変数に足し込む
               Case "B"
                    vConv = vConv + Chr$(vUpByte) + Chr$(vDownByte)  'ワーク変数に足し込む
               Case Else
                    vConv = vConv + Hex(vUpByte) + Hex(vDownByte)    'ワーク変数に足し込む
        End Select
    Next i
    
    Kanji_Conv = vConv

End Function

引用返信 編集キー/
■36578 / inTopicNo.2)  Re[1]: JISコード⇒シフトJISコードに変換し形式をHEX
□投稿者/ επιστημη (1947回)-(2009/06/02(Tue) 10:23:54)
επιστημη さんの Web サイト
> 以下の逆でJISコード⇒シフトJISコードに変換し形式をHEXにするにはどうすればよいでしょうか?

Shift-JIS→JISの変換規則がコードから明らかなんだから
こいつを裏返すだけだと思うんだけど、何がわからんですか?

引用返信 編集キー/
■36594 / inTopicNo.3)  Re:JISコード⇒シフトJISコードに変換し形式をHEX
□投稿者/ 魔界の仮面弁士 (1114回)-(2009/06/02(Tue) 11:58:45)
2009/06/02(Tue) 12:47:14 編集(投稿者)
No36576 (ooo さん) に返信
> 変換後の形式をHEXおよびバイナリに変換する関数となります。
これには、半角英数字などが渡された場合の処理が組み込まれていますか?

今の実装のままだと、漢字IN/OUT を必要とする文字列が渡された場合、
データ破損を引き起こす可能性があるかと思います。

実際、こちらの環境で検証したところ、
 X = Kanji_Conv("B", "[=≠ab]")
 Y = Kanji_Conv("B", "(=≠ab)")
とした場合、X と Y は同一の結果を返してきてしまいましたし。


> Public Function Kanji_Conv(psPara As String, psSiftJis As String) As String

32bit版 VB における String 型というのは、常に Unicode でエンコードされています。
日本語環境においては、(VB の標準入出力命令によって)Shift_JIS に変換されて
やりとりされるというだけであって、String の中身が Shift_JIS という訳では無いかと。

なお、ChrB/AscB/ChrW/AscW/MidB 等は、文字コードの変換作業を伴いませんが、
Chr/Asc/Mid/Left/Right/MsgBox 等は、Unicode と Shift_JIS 間の相互変換を伴うため、
「Shift_JIS に無い範囲のデータ」が渡されると、データ破損等の問題を引き起こします。

そのため、VB6 における文字コード変換の際には、String 型でやりとりするのではなく、
Byte 配列を通じてやり取りする事が推奨されています。これは VB6 のステートメントが、
String 型が Unicode ベースで管理されている事を前提に設計されているため、
String をそのまま使うと、暗黙の文字コード変換に伴うデータ破損を引き起こすためです。


> psSiftJis As String
sift  … ふるいに書ける
shift … ずらす


> JISコート゛⇒シフトJISコート゛に変換し
単純に、JIS バイナリをデコードしたいというだけであれば、下記のように書けます。
EUC-JP など、他の文字コードの場合にも応用できるので、比較的楽かと。

'Microsoft ActiveX Data Objects (2.5 以上)のライブラリを参照設定
Public Function StringFromJISBinary(ByRef JIS() As Byte) As String
    Dim stm As ADODB.Stream
    Set stm = New ADODB.Stream
    stm.Type = adTypeBinary
    stm.Open
    stm.Write JIS   'バイナリモードにして、生バイナリを書き込む
    stm.Position = 0
    stm.Type = adTypeText
    stm.Charset = "ISO-2022-JP"  'テキストモードに変更し、JIS テキストとして読み込む
    StringFromJISBinary = stm.ReadText(adReadAll)
    stm.Close
End Function


> 形式をHEXにするにはどうすればよいでしょうか
バイナリを16進数文字列に表現したいのであれば、このように書けます。
Hex 関数を繰り返し使うよりも楽かと。

Public Function ToHexString(ByRef bin() As Byte) As String
    With CreateObject("Microsoft.XMLDOM").createElement("h")
        .DataType = "bin.hex"
        .NodeTypedValue = bin
        ToHexString = .Text
    End With
End Function

引用返信 編集キー/
■36600 / inTopicNo.4)  Re[2]: JISコード⇒シフトJISコードに変換し形式をHEX
□投稿者/ ooo (36回)-(2009/06/02(Tue) 13:46:53)
単純に下記でいけました。
ありがとうございました

'***************************************************************************************************
'------------------------
'FUNCTION情報
'------------------------
'FUN名  :S_Jis_Conv
'処理概要    :変換処理
'              引数文字をS-JISに変換する
'引数1    :psSiftJis    IN  変換対象値
'
'戻り値      :変換値
'***************************************************************************************************
Public Function S_Jis_Conv(psSiftJis As String) As String
Rem シフトJISコードへ変換
'   psSiftJis   :   シフトJISコード

    Dim i As Integer                                '桁数のリターンコード
    Dim vConv                                       'ワーク変数
    Dim vHex                                        '4バイトのシフトJISコードに変換のリターンコード
    
    vConv = ""                                      'ワーク変数の初期化
    For i = 1 To Len(psSiftJis)                     '桁数分繰り返す
        vHex = Hex(Asc(Mid$(psSiftJis, i, 1)))      '4バイトのシフトJISコードに変換
        vConv = vConv + vHex
    Next i
    
    S_Jis_Conv = vConv

End Function

解決済み
引用返信 編集キー/
■36601 / inTopicNo.5)  Re[3]: JISコード⇒シフトJISコードに変換し形式をHEX
□投稿者/ みきぬ (452回)-(2009/06/02(Tue) 13:54:52)
えっと、全然解決してないような気がするので、チェックを外しておきますね。
引用返信 編集キー/
■36622 / inTopicNo.6)  Re[3]: JISコード⇒シフトJISコードに変換し形式をHEX
□投稿者/ 魔界の仮面弁士 (1115回)-(2009/06/02(Tue) 17:26:24)
No36600 (ooo さん) に返信
> Public Function S_Jis_Conv(psSiftJis As String) As String
引数は ByRef ではなく、ByVal にしておいた方が、呼び出し時に楽ですよ。


> '   psSiftJis   :   シフトJISコード
シフト JIS のスペルは、Shift JIS です。
shift と sift では意味が異なりますのでご注意を。


>    Dim vConv
>    Dim vHex
型を明示指定しましょう。この場合は、
 Dim vConv As String
 Dim vHex As String
が適切かと思います。


>    vHex = Hex(Asc(Mid$(psSiftJis, i, 1)))      '4ハ゛イトのシフトJISコート゛に変換
この部分、桁数をそろえた方が安全かと思います。

例えば、
 psSiftJis = "あ"
であれば、vHex は「82A0」という 4 文字(≠4バイト)が得られますが、
 psSiftJis = "="
の場合には、vHex は「3D」という 2 文字となります。そして、
 psSiftJis = vbTab
の場合には、vHex は「9」という 1 文字になってしまいます。



>  vConv = vConv + vHex
文字列連結演算子「&」と、加算演算子「+」を使い分ける事を、強くお奨めします。

これが、
 Dim vConv As String
 Dim vHex As String
のように、String 型と明示してある場合には「+」でも文字列連結として処理されますが、
Variant 型同士の場合、内部データ型に応じてその振る舞いが変化するためです。

もし「文字列 + 数値」の演算が行われた場合、VB は文字列連結ではなく
加算として処理する仕様になっています。

今回の場合は文字列型同士なので、「+」でも常に文字列連結として扱われますが、
文字列の連結である事を明らかにするためにも、「&」で繋いだ方が良いでしょう。


という事で、先の No36600 にあるループ処理の修正案。

For i = 1 To Len(psSiftJis)
    Dim c As Integer
    c = Asc(Mid$(psSiftJis, i, 1))
    If c < 0 Or c > 255 Then
        vHex = Right$("0000" & Hex(c), 4)
    Else
        vHex = Right$("00" & Hex(c), 2)
    End If
    vConv = vConv & vHex
Next i



ついでに、ループを使わないコード。

Public Function S_Jis_Conv(ByVal psSJis As String) As String
    Dim sjis() As Byte
    sjis = StrConv(psSJis, vbFromUnicode)
    With CreateObject("Microsoft.XMLDOM").createElement("u")
        .DataType = "bin.hex"
        .NodeTypedValue = sjis
        S_Jis_Conv = UCase(.Text)
    End With
End Function

解決済み
引用返信 編集キー/
■36652 / inTopicNo.7)  Re[4]: JISコード⇒シフトJISコードに変換し形式をHEX
□投稿者/ ooo (37回)-(2009/06/03(Wed) 11:38:30)
2009/06/03(Wed) 11:39:13 編集(投稿者)
2009/06/03(Wed) 11:39:07 編集(投稿者)
2009/06/03(Wed) 11:39:03 編集(投稿者)

<pre><pre>魔界の仮面弁士さん

コードレビューまでしていただきましてありがとうございます。
また改善案まで・・
しかもタイトルの「JISコード⇒シフトJISコードに変換し形式をHEX」の部分と
もはや関係のない世界に突入してしまいました。

なぜそんなことを聞いたのかといいますと。
SBPLにリンクします。
http://bbs.wankuma.com/index.cgi?mode=al2&namber=36317

SBPLというプログラミング言語を介して、VBにてラベルプリンタの制御を行っております。
そこで、漢字文字、半角文字混在の場合は、文字コードをShiftJisかつHEXにて送る必要がありまして、
今回のトピックを挙げさせていただきました。

全容はそんな感じです。
皆様、ありがとうございました。</pre></pre>
解決済み
引用返信 編集キー/
■36654 / inTopicNo.8)  Re[5]: JISコード⇒シフトJISコードに変換し形式をHEX
□投稿者/ ooo (39回)-(2009/06/03(Wed) 12:10:49)
魔界の仮面弁士さん

ヘルプで調べても下記コードがわけわかめでした・・・。

>Public Function S_Jis_Conv(ByVal psSJis As String) As String
> Dim sjis() As Byte
> sjis = StrConv(psSJis, vbFromUnicode)
> With CreateObject("Microsoft.XMLDOM").createElement("u")
> .DataType = "bin.hex"
> .NodeTypedValue = sjis
> S_Jis_Conv = UCase(.Text)
> End With
>End Function

せっかくなのでお時間がよろしければ解説いただけませんでしょうか?
図々しくてすみません。
引用返信 編集キー/
■36655 / inTopicNo.9)  Re[6]: JISコード⇒シフトJISコードに変換し形式をHEX
□投稿者/ ooo (40回)-(2009/06/03(Wed) 12:11:14)
No36654 (ooo さん) に返信
> 魔界の仮面弁士さん
> 
> ヘルプで調べても下記コードがわけわかめでした・・・。
> 
> >Public Function S_Jis_Conv(ByVal psSJis As String) As String
>>   Dim sjis() As Byte
>>   sjis = StrConv(psSJis, vbFromUnicode)
>>   With CreateObject("Microsoft.XMLDOM").createElement("u")
>>       .DataType = "bin.hex"
>>       .NodeTypedValue = sjis
>>       S_Jis_Conv = UCase(.Text)
>>   End With
> >End Function
> 
> せっかくなのでお時間がよろしければ解説いただけませんでしょうか?
> 図々しくてすみません。

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -