お世話になります。
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バイト付けるものなのでしょうか。
何かめんどくさいです。
ご存知の方、ご教示下さい。
よろしくお願いいたします。
> 先頭の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" と同じバイナリなのです。
後続のバイナリの解釈を切り替えるために挿入される重要なデータなので、
これらが失われると、文字列の意味が変わってしまったりします。(^^;
# ただし、データ中の漢字モードが固定されている場合などは、データ量を
# 削減する為、これらのエスケープシーケンスが省略される事もあります。
理由は魔界の仮面弁士さんの説明参照していただくとして
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
#バイト単位に分離したり結合したりと色々面倒ですが・・・。
魔界の仮面弁士様 有難うございます。
># ただし、データ中の漢字モードが固定されている場合などは、データ量を
># 削減する為、これらのエスケープシーケンスが省略される事もあります。
と言うことは、今回読み込んだファイルは(固定長テキスト)この省略された形だと言うことですね。
以前、汎用機を使っていた時漢字の前に 0E 後に 0F が付いていたのを思い出しました。
面倒ですが、無理やり読み込んだ文字列の前後にエスケープコードを付けて
変換しようと思います。
へむりんさん、有難うございます。
いままで、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(月) 12:01:39
>魔界の仮面弁士様 有難うございます。
~~~~
>若菜 2006/02/20(月) 12:10:39
>へむりんさん、有難うございます。
~~~~~
へむりん様、大変失礼致しました。
別に他意はございません。
お許し下さい・・・
有難うございました
解決しました。
ツイート | ![]() |