JISからシフトJISへ変換

解決


若菜  2006-02-20 19:04:10  No: 94297

お世話になります。
JISからシフトJISへ変換するコードです。
ファイルを読み込み最初の27バイトは、EBCDIC次の50バイトは、JISです。

    sub Main
        Dim iFile As String = "z:\02171631.syo"
        Dim fs As New System.IO.FileStream(ifile, IO.FileMode.Open)
        Dim i As Integer
        Dim dt(127) As Byte

        For i = 1 To 10

            System.Windows.Forms.Application.DoEvents()

            fs.Read(dt, 0, 128) '<--- 第3引数はバイト数

            If EtoA(dt, 3, 1) = "D" Then
                Debug.WriteLine(JisToSjis(dt, 28, 50)) '<---ここ
            End If

        Next i

        fs.Close()

    End Sub

'''問題のコード
    Function JisToSjis(ByVal bytes() As Byte, ByVal start As Short, ByVal length As Short) As String

        Dim str As String = _
            System.Text.Encoding.GetEncoding(50220).GetString(bytes, start - 1, length)

        Return str

    End Function

これで、上手くいくと思ったのですがダメでした。
そこで、試しに
    sub test
        Dim str As String = "AB"

        Dim bytesData As Byte() = _
            System.Text.Encoding.GetEncoding(50220).GetBytes(str)

        Debug.Print(Hex(bytesData(0)) & vbTab & Hex(bytesData(1)) & vbTab & Hex(bytesData(2)) & vbTab & Hex(bytesData(3)) & vbTab & Hex(bytesData(4)) & vbTab & Hex(bytesData(5)) & vbTab & Hex(bytesData(6)) & vbTab & Hex(bytesData(7)) & vbTab & Hex(bytesData(8)) & vbTab & Hex(bytesData(9)))
    end sub
私は、4バイトの配列が出来ると思ったのですが10バイトの配列が出来ました。
よく調べてみると、
先頭 1B 24 42
末尾 1B 28 42
が何時も出来ることがわかりました。
そこで先ほどのJisToSjisに先頭に1B 24 42 末尾に1B 28 42をくっ付けてエンコードしてやると
上手くJISからシフトJISに変換できました。

質問なのですが、
①先頭の1B 24 42 末尾の1B 28 42は何なのでしょうか。
②JISからシフトJISに変換する時
  System.Text.Encoding.GetEncoding(50220).GetBytes
  は、先頭に3バイト末尾に3バイト付けるものなのでしょうか。
  何かめんどくさいです。

ご存知の方、ご教示下さい。
よろしくお願いいたします。


魔界の仮面弁士  2006-02-20 20:12:47  No: 94298

> 先頭の1B 24 42 末尾の1B 28 42は何なのでしょうか。

1B で始まるバイナリは、漢字IN/漢字OUT のエスケープシーケンスです。

「1B 24 42」以降のバイト列は、JIS X 0208-1983 として扱われますが、
「1B 28 42」以降のバイト列は、単に ASCII として解釈されるのです。
http://www.asahi-net.or.jp/~wq6k-yn/code/esc.html

例えば、"入門" という文字列は、「46 7E 4C 67」で表されますが、
これは "F~Lg" と文字列と、全く同じバイナリですし、また、
"VB" は「23 56 23 42」で、これは "#V#B" と同じバイナリなのです。

後続のバイナリの解釈を切り替えるために挿入される重要なデータなので、
これらが失われると、文字列の意味が変わってしまったりします。(^^;

# ただし、データ中の漢字モードが固定されている場合などは、データ量を
# 削減する為、これらのエスケープシーケンスが省略される事もあります。


へむりん  2006-02-20 20:54:08  No: 94299

理由は魔界の仮面弁士さんの説明参照していただくとして

JIS50バイトが必ず漢字ということであれば
↓なんていうのもありかもです。(あんまりテストしてません)

Private Sub Command1_Click()

Dim knj1 As Integer
Dim knj2 As Integer

' JIS A(&h2341)
knj1 = &H23
knj2 = &H41
Call JTosjis(knj1, knj2)

Debug.Print Hex(knj1), Hex(knj2) '&h8260
  
' JIS B(&h2342)
knj1 = &H23
knj2 = &H42
Call JTosjis(knj1, knj2)
  
Debug.Print Hex(knj1), Hex(knj2) '&h8261

End Sub

Private Sub JTosjis(ByRef knj1 As Integer, ByRef knj2 As Integer)
  If knj1 And &H1 Then
    knj1 = Fix(knj1 / 2)
    If knj1 < &H2F Then knj1 = knj1 + &H71 Else knj1 = knj1 - &H4F
    If knj2 > &H5F Then knj2 = knj2 + &H20 Else knj2 = knj2 + &H1F
  Else
    knj1 = Fix(knj1 / 2)
    If knj1 < &H2F Then knj1 = knj1 + &H70 Else knj1 = knj1 - &H50
    knj2 = knj2 + &H7E
  End If
End Sub

#バイト単位に分離したり結合したりと色々面倒ですが・・・。


若菜  2006-02-20 21:01:39  No: 94300

魔界の仮面弁士様  有難うございます。

># ただし、データ中の漢字モードが固定されている場合などは、データ量を
># 削減する為、これらのエスケープシーケンスが省略される事もあります。

と言うことは、今回読み込んだファイルは(固定長テキスト)この省略された形だと言うことですね。

以前、汎用機を使っていた時漢字の前に 0E 後に 0F が付いていたのを思い出しました。
面倒ですが、無理やり読み込んだ文字列の前後にエスケープコードを付けて
変換しようと思います。


若菜  2006-02-20 21:10:39  No: 94301

へむりんさん、有難うございます。

いままで、VB6の時は、
Private Function JisToSjis(ByRef Kst() As Byte, Optional ByVal s As Integer, Optional ByVal e As Integer) As String

    Dim Hx As String
    Dim Ah As Long
    Dim Al As Byte
    Dim cn As Long

    If e = 0 Then e = UBound(Kst)

    For cn = s To e Step 2
        
        Ah = Kst(cn)
        Al = Kst(cn + 1)
        
        'JIS→シフトJIS変換
        
        If (Ah Mod 2) = 0 Then
            Ah = Ah - 1
            Al = Al + &H7D
        Else
            Al = Al + &H1F
        End If
        
        If Al > &H7E Then
            Al = Al + 1
        End If
        
        Ah = (Ah - &H21) / 2 + &H81
        If Ah > &H9F Then
            Ah = Ah + &H40
        End If
        
        Ah = Ah And &HFF
        Al = Al And &HFF
        
        JisToSjis = JisToSjis & Chr$(256 * Ah + Al)
    
    Next cn
    
End Function

とやっていたのですが、今回VB 2005に移植する時に
どうせなら、.NET Framework ぽく?やろうと思いはまってしまいました。


若菜  2006-02-20 21:15:22  No: 94302

>若菜 2006/02/20(月) 12:01:39
>魔界の仮面弁士様  有難うございます。
              ~~~~
>若菜 2006/02/20(月) 12:10:39
>へむりんさん、有難うございます。
         ~~~~~ 
へむりん様、大変失礼致しました。
別に他意はございません。
お許し下さい・・・


若菜  2006-02-20 23:47:09  No: 94303

有難うございました
解決しました。


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

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






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