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

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

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

Re[6]: バイト配列の変換について


(過去ログ 171 を表示中)

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

■98386 / inTopicNo.1)  バイト配列の変換について
  
□投稿者/ めんこ (1回)-(2021/11/12(Fri) 13:38:51)

分類:[VB.NET/VB2005 以降] 

よろしくお願いします。
2バイトコードの文字化けの文字を変換すると違う文字に置き換わってしまいます。
文字化けコードなので、処理で自動的に置き換わっていると思うのですが
このコードを取得したいので、何か対処ありますでしょうか。


Dim strEn As String
Dim bytes As Byte() = New Byte(1) {&H81, &HC5}
strEn = System.Text.Encoding.GetEncoding(932).GetString(bytes)

strEn の値が「81 45」に置き換わってしまいます。

引用返信 編集キー/
■98387 / inTopicNo.2)  Re[1]: バイト配列の変換について
□投稿者/ 古谷 (17回)-(2021/11/12(Fri) 14:10:18)
No98386 (めんこ さん) に返信

「81 45」を取得したいってこと?

Dim destBytes As Byte() = System.Text.Encoding.GetEncoding(932).GetBytes(strEn)
Dim b As Byte

For Each b In destBytes
    Console.WriteLine(Convert.ToString(b, 16))
Next

引用返信 編集キー/
■98388 / inTopicNo.3)  Re[2]: バイト配列の変換について
□投稿者/ めんこ (2回)-(2021/11/12(Fri) 14:14:56)
> 「81 45」を取得したいってこと?

「81 C5」を取得したいのですが、勝手に「81 45」に置き換わっています。

ファイル出力するのに「81 C5」を送りたいのですが、置き換わってしまうので、
エンコード変えたりしているのですが、まだ対処出来ていないです。
引用返信 編集キー/
■98389 / inTopicNo.4)  Re[1]: バイト配列の変換について
□投稿者/ くま (29回)-(2021/11/12(Fri) 14:23:38)
文字列のコードが分からないのであれば以下のような方法が簡単です
1. バイト配列を文字列に変換
2. 変換された文字列を再度バイト配列に変換
3. バイト配列と再変換バイト配列が同じなら変換成功

    Dim bytIn As Byte() = New Byte(1) {&H81, &HC5}
    Dim strEn As string = ByteToString(bytIn)

    Function ByteToString(ByRef bytIn As Byte()) As String
        Dim strText As String = ""
        Dim bytOut() As Byte = {}

        'Shift JIS 判定
        strText = System.Text.Encoding.GetEncoding(932).GetString(bytIn)
        bytOut = System.Text.Encoding.GetEncoding(932).GetBytes(strText)
        If System.Linq.Enumerable.SequenceEqual(bytIn, bytOut) Then
            Return strText
        End If

        'JIS 判定
        strText = System.Text.Encoding.GetEncoding(50220).GetString(bytIn)
        bytOut = System.Text.Encoding.GetEncoding(50220).GetBytes(strText)
        If System.Linq.Enumerable.SequenceEqual(bytIn, bytOut) Then
            Return strText
        End If

        'EUC 判定
        strText = System.Text.Encoding.GetEncoding(50220).GetString(bytIn)
        bytOut = System.Text.Encoding.GetEncoding(50220).GetBytes(strText)
        If System.Linq.Enumerable.SequenceEqual(bytIn, bytOut) Then
            Return strText
        End If

        'UTF-8 判定
        strText = System.Text.Encoding.UTF8.GetString(bytIn)
        bytOut = System.Text.Encoding.UTF8.GetBytes(strText)
        If System.Linq.Enumerable.SequenceEqual(bytIn, bytOut) Then
            Return strText
        End If

        strText = ""
        Throw New Exception("Byte配列の変換に失敗しました。")
        Return strText
    End Function

引用返信 編集キー/
■98390 / inTopicNo.5)  Re[1]: バイト配列の変換について
□投稿者/ WebSurfer (2375回)-(2021/11/12(Fri) 14:37:20)
No98386 (めんこ さん) に返信

> strEn の値が「81 45」に置き換わってしまいます。

そんなことはないと思うのですが。どこの何を見てそう言っているのでしょう?
デバッガを使って調べてみては以下かがですか?
引用返信 編集キー/
■98391 / inTopicNo.6)  Re[2]: バイト配列の変換について
□投稿者/ めんこ (3回)-(2021/11/12(Fri) 14:46:46)
No98390 (WebSurfer さん) に返信
> ■No98386 (めんこ さん) に返信
>
>>strEn の値が「81 45」に置き換わってしまいます。
>
> そんなことはないと思うのですが。どこの何を見てそう言っているのでしょう?
> デバッガを使って調べてみては以下かがですか?

デバッグ上のイミディエイトウインドで
?System.Text.Encoding.GetEncoding(932).GetBytes(strEn)
{Length=2}
(0): 129
(1): 69
で返ってきます。
&H81=129 で &HC5=197ですが、かわっています。
ファイル出力して、秀丸エディタのバイナリーモードで確認すると、「81 45」になっています。

引用返信 編集キー/
■98392 / inTopicNo.7)  Re[3]: バイト配列の変換について
□投稿者/ WebSurfer (2376回)-(2021/11/12(Fri) 15:03:05)
No98391 (めんこ さん) に返信

> &H81=129 で &HC5=197ですが、かわっています。
> ファイル出力して、秀丸エディタのバイナリーモードで確認すると、「81 45」になっています。

分かりました。

0x81C5 は Shift_JIS として文字が存在しないので、

strEn = System.Text.Encoding.GetEncoding(932).GetString(bytes)

で「・」(0x8145) に置き換えてしまうようです。

それは仕様なのか何なのかは分かりませんが・・・

IME パッドでも文字が存在しないと「・」が表示されて、マウスのカーソルを当てると Shift JIS 0x8145
と表示されます。そういうものなのかも。
引用返信 編集キー/
■98393 / inTopicNo.8)  Re[4]: バイト配列の変換について
□投稿者/ めんこ (4回)-(2021/11/12(Fri) 15:08:13)
No98392 (WebSurfer さん) に返信
> ■No98391 (めんこ さん) に返信
>
>>&H81=129 で &HC5=197ですが、かわっています。
>>ファイル出力して、秀丸エディタのバイナリーモードで確認すると、「81 45」になっています。
>
> 分かりました。
>
> 0x81C5 は Shift_JIS として文字が存在しないので、
>
> strEn = System.Text.Encoding.GetEncoding(932).GetString(bytes)
>
> で「・」(0x8145) に置き換えてしまうようです。
>
> それは仕様なのか何なのかは分かりませんが・・・
>
> IME パッドでも文字が存在しないと「・」が表示されて、マウスのカーソルを当てると Shift JIS 0x8145
> と表示されます。そういうものなのかも。

回答ありがとうございます。
私も方もおそらく仕様だと思っているのですが、別の方法でも回避できる方法ないかなと思って
色々調べているのですが、見つからずこちらで詳しい方いらっしゃるかなと。。

引用返信 編集キー/
■98394 / inTopicNo.9)  Re[5]: バイト配列の変換について
□投稿者/ 古谷 (18回)-(2021/11/12(Fri) 15:26:30)
デコードせずにバイナリをそのままファイルに出力すればよい気がする
引用返信 編集キー/
■98395 / inTopicNo.10)  Re[6]: バイト配列の変換について
□投稿者/ 古谷 (19回)-(2021/11/12(Fri) 15:35:53)
文字コードを変換するなら大変かもね
byte配列をいじってできないことはないだろうけど
元のデータをUTF-8とかでもらうことできないん? それが手っ取り早いと思った
引用返信 編集キー/
■98396 / inTopicNo.11)  Re[1]: バイト配列の変換について
□投稿者/ 魔界の仮面弁士 (3210回)-(2021/11/12(Fri) 15:41:01)
No98386 (めんこ さん) に返信
> 文字化けコードなので、処理で自動的に置き換わっていると思うのですが
> このコードを取得したいので、何か対処ありますでしょうか。

GetEncoding メソッドの 第3引数に DecoderFallback.ExceptionFallback を指定して
Catch ex As DecoderFallbackException を拾ってみてください。
引用返信 編集キー/
■98397 / inTopicNo.12)  Re[2]: バイト配列の変換について
□投稿者/ めんこ (5回)-(2021/11/12(Fri) 15:48:09)
No98396 (魔界の仮面弁士 さん) に返信
> ■No98386 (めんこ さん) に返信
>>文字化けコードなので、処理で自動的に置き換わっていると思うのですが
>>このコードを取得したいので、何か対処ありますでしょうか。
>
> GetEncoding メソッドの 第3引数に DecoderFallback.ExceptionFallback を指定して
> Catch ex As DecoderFallbackException を拾ってみてください。

下記エラーになりました。
インデックス 0 にあるバイト [81][C5] を指定されたコード ページから Unicode へ変換できません。
引用返信 編集キー/
■98398 / inTopicNo.13)  Re[7]: バイト配列の変換について
□投稿者/ めんこ (6回)-(2021/11/12(Fri) 15:48:43)
No98395 (古谷 さん) に返信
> 文字コードを変換するなら大変かもね
> byte配列をいじってできないことはないだろうけど
> 元のデータをUTF-8とかでもらうことできないん? それが手っ取り早いと思った

出来ればよいのですが、出力ファイルがShift_JISでの仕様なんです。。
引用返信 編集キー/
■98399 / inTopicNo.14)  Re[3]: バイト配列の変換について
□投稿者/ 魔界の仮面弁士 (3211回)-(2021/11/12(Fri) 16:00:23)
No98397 (めんこ さん) に返信
>>GetEncoding メソッドの 第3引数に DecoderFallback.ExceptionFallback を指定して
> 下記エラーになりました。
> インデックス 0 にあるバイト [81][C5] を指定されたコード ページから Unicode へ変換できません。

だからこそ

>>Catch ex As DecoderFallbackException を拾ってみてください。

が必要というわけで。
引用返信 編集キー/
■98400 / inTopicNo.15)  Re[4]: バイト配列の変換について
□投稿者/ めんこ (7回)-(2021/11/12(Fri) 16:17:55)
No98399 (魔界の仮面弁士 さん) に返信

> >>Catch ex As DecoderFallbackException を拾ってみてください。
>
> が必要というわけで。

下記でしてみたのですが、どこか間違えていますでしょうか。

Try

Dim strEn As String
Dim bytes As Byte() = New Byte(1) {&H81, &HC5}
Dim encoderFallback As EncoderReplacementFallback = New EncoderReplacementFallback("あ")

strEn =System.Text.Encoding.GetEncoding(932, encoderFallback, DecoderFallback.ExceptionFallback).GetString(bytes)

Catch ex As DecoderFallbackException
Debug.Print(ex.Message)
End Try

引用返信 編集キー/
■98401 / inTopicNo.16)  Re[5]: バイト配列の変換について
□投稿者/ PATIO (15回)-(2021/11/12(Fri) 17:02:43)
2021/11/12(Fri) 17:08:50 編集(投稿者)
2021/11/12(Fri) 17:05:41 編集(投稿者)

No98400 (めんこ さん) に返信
> ■No98399 (魔界の仮面弁士 さん) に返信
>
>>>>Catch ex As DecoderFallbackException を拾ってみてください。
>>
>>が必要というわけで。
>
> 下記でしてみたのですが、どこか間違えていますでしょうか。
>
> Try
>
> Dim strEn As String
> Dim bytes As Byte() = New Byte(1) {&H81, &HC5}
> Dim encoderFallback As EncoderReplacementFallback = New EncoderReplacementFallback("あ")
>
> strEn =System.Text.Encoding.GetEncoding(932, encoderFallback, DecoderFallback.ExceptionFallback).GetString(bytes)
>
> Catch ex As DecoderFallbackException
> Debug.Print(ex.Message)
> End Try
>

えーと結局何がしたいのでしょう?
ShiftJISに存在しないコードをShiftJISでエンコードしようとするのが、そもそも問題なのでは?
ファイルに出力したいだけなら古谷さんが言われているようにバイナリで出力するしかないと思います。
もしくは文字としてではなく81C5という文字コードを文字列化して出力するかです。
エンコードすると代替え文字に置き換わるのは仕様だと思うのでこれをどうこうするのは無理だと思います。

それとも文字化けしている事を検出したいのでしょうか?
それだったら言われているように例外で引っ掛けるのが一番素直かも。
変換して例外が出れば文字化けコードなので変換前の文字コードを文字列化して出力するとか。
引用返信 編集キー/
■98403 / inTopicNo.17)  Re[5]: バイト配列の変換について
□投稿者/ 魔界の仮面弁士 (3213回)-(2021/11/12(Fri) 17:15:36)
No98400 (めんこ さん) に返信
> 下記でしてみたのですが、どこか間違えていますでしょうか。

逆に質問してみますが、何を期待して、実際にはどうなってしまっていますか?


そもそもの質問内容は、
>>> 文字化けコードなので、処理で自動的に置き換わっていると思うのですが
>>> このコードを取得したいので
でしたよね。

それを知る方法として、
>>Catch ex As DecoderFallbackException を拾ってみてください
を紹介しました。

GetEncoding の第2/第3引数に対しては、
 不正なデータを何らかの代替文字へ置き換えて処理するなら、EncoderReplacementFallback/DecoderReplacementFallback
 不正なデータを変換エラーとして捉えて処理するなら、EncoderExceptionFallback/DecoderExceptionFallback
を指定するようになっています。そしてこのうち、後者の手法を採った際には、その変換エラーが
EncoderFallbackException/DecoderFallbackException としてスローされる仕様です。


後者の方法であれば、文字コード変換の際に、不正データがあったかどうかを確認できますし、
不正データがあったとして、それがどの位置の何というコードだったのかを調べる事が出来ます。
また、例外処理を使えば、そのエラーをログとして残したり、あるいはデータ提供元に対して、
不正では無いデータの再提出を依頼するような仕組みを設けたりもできるでしょう。


そしてその結果、実際にお書きになったコードというのが
> Catch ex As DecoderFallbackException
> Debug.Print(ex.Message)
だったわけですが…結果として、Message の出力だけでは十分な結果が得られなかったということでしょうか?

それが求める結果と違っているというのであれば、どういう結果が欲しいのか、
あるいはどのような動作を期待しているのか明確に示してみてください。

「どこか間違えていますでしょうか」と聞かれましても、
そもそも何を期待してそのコードを書いたのかを説明して頂かないと、判断が付かないです。


で…どういう動作を期待しているにせよ、単に Message を得るだけであれば、
 Catch ex As Exception
でもあまり変わらないと思います。しかし、折角、
 Catch ex As DecoderFallbackException
を使っているのですから、この例外クラスならではメンバーも確認しておいた方が良いのでは無いでしょうか?
https://docs.microsoft.com/ja-jp/dotnet/api/system.text.encoderfallbackexception?view=netframework-4.8
引用返信 編集キー/
■98404 / inTopicNo.18)  Re[6]: バイト配列の変換について
□投稿者/ めんこ (8回)-(2021/11/12(Fri) 17:21:40)
No98401 (PATIO さん) に返信
>
>
> えーと結局何がしたいのでしょう?
> ShiftJISに存在しないコードをShiftJISでエンコードしようとするのが、そもそも問題なのでは?
> ファイルに出力したいだけなら古谷さんが言われているようにバイナリで出力するしかないと思います。
> もしくは文字としてではなく81C5という文字コードを文字列化して出力するかです。
> エンコードすると代替え文字に置き換わるのは仕様だと思うのでこれをどうこうするのは無理だと思います。
>
> それとも文字化けしている事を検出したいのでしょうか?
> それだったら言われているように例外で引っ掛けるのが一番素直かも。
> 変換して例外が出れば文字化けコードなので変換前の文字コードを文字列化して出力するとか。

“81h C5h” (2バイトコード)で出力することを求められており、いろいろ試行錯誤してたのですが
置き換わるのが仕様みたいだったので、他の方法で出力することが可能かをお聞きしてました。
やはり難しいというか無理そうですね。
仕様の見直し出来るか相談してみます。。

皆様いろいろご回答ありがとうございました。
良い案があれば教えて頂いたいですが、一旦解決とさせて頂きます。

解決済み
引用返信 編集キー/
■98405 / inTopicNo.19)  Re[7]: バイト配列の変換について
□投稿者/ 魔界の仮面弁士 (3214回)-(2021/11/12(Fri) 19:00:40)
No98404 (めんこ さん) に返信
> “81h C5h” (2バイトコード)で出力することを求められており、
であれば、
 Dim bytes As Byte() = {&H81, &HC5}
だけで済みそうですね。

そもそも「バイトコード」を出力することを最終目的としているのであれば、
GetString で「文字列」に変換しているのが不自然であったと言えます。

文字列型にはそもそも「文字コード」という情報が含まれていませんし、
.NET の文字列型の「文字集合」は Unicode 前提だからです。


一応、コードページ 932 を Unicode 変換するための資料を貼っておきます。
http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP932.TXT
http://unicode.org/Public/MAPPINGS/OBSOLETE/EASTASIA/JIS/JIS0208.TXT
https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/bestfit932.txt


0x8145 は Unicode の U+30FB [KATAKANA MIDDLE DOT] への対応となっていますが、
0x81C5 に対する変換ルールは未定義であることが上記から分かります。
DecoderFallbackException が投げられたのもそのためでしょう。


もしも Shift_JIS-2004 であったなら、0x81C5 が Unicode の U+2205 [EMPTY SET] に対応しますが、
この文字は コードページ 932 の文字集合には含まれていない文字なので、今回は関係無いですね。


そして仮に変換エラーとならない文字であったとしても、
同じ文字が異なるコードポイントに重複登録されていた場合には、
.NET の String 型で扱った際に、不可逆変換になってしまう可能性があります。

Shift_JIS であれば、「NEC特殊文字」「NEC選定IBM特殊非漢字」「IBM特殊非漢字」の一部など。


具体例の一つはルート記号 √ 。
これは 0x81E3 と 0x8795 の 2 箇所に配置されていますが、Unicode 上は U+221A として扱われます。

あるいは全角否定記号 ¬ 。
これは 0x81CA と 0xEEF9 と 0xFA54 の 3 箇所に配置されていますが、Unicode では U+FFE2 です。
解決済み
引用返信 編集キー/
■98406 / inTopicNo.20)  Re[7]: バイト配列の変換について
 
□投稿者/ KOZ (166回)-(2021/11/13(Sat) 07:28:41)
2021/11/13(Sat) 08:11:17 編集(投稿者)
2021/11/13(Sat) 07:39:27 編集(投稿者)

No98404 (めんこ さん) に返信
> “81h C5h” (2バイトコード)で出力することを求められており、いろいろ試行錯誤してたのですが

BitConverter を使えばいい話なのでは?

Dim bytes As Byte() = New Byte(1) {&H81, &HC5}
Dim strEn As String = New String(BitConverter.ToChar(bytes, 0), 1)

# すみません。読み飛ばして変なレスつけちゃいました。
解決済み
引用返信 編集キー/

次の20件>
トピック内ページ移動 / << 0 | 1 >>

管理者用

- Child Tree -