@Kou1024

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

シリアル通信で送信した半角カナが文字化けする現象について

発生している問題

文字コードと電文制御についての質問となります。
PCからラベラプリンタへシリアル通信でラベルデータを送信しているのですが、QRコードのデータ部において、半角カナを送信しラベル発行した際に、QRをカメラで認識すると半角カナのみ?となってしまう現象で悩んでおります

VB6で開発されたプログラムをVB.NETへ更新を試みており、以前使用していたコードと同様に記述しています。全角文字はJIS変換をし、16進数の2バイトで送信、こちらは問題なく印字できております。

半角カナは変換をかけずにそのまま送信しておりましたので、同じようにそのまま送信しましたが、文字化けが発生してしまいます。VB6.0のプログラムで印字したQRでは問題なく半角カナが読めています。

ラベラメーカーに問い合わせしておりますがこちらでも質問させていただきます。

[追記]

皆様のコメントで気が付いたことがありますので記述していきます。
VB6からVB.Netに移行し、シリアル通信のメソッドの記述が変わっています。
現在は、コード内で

SerialPort1.Write(str)

として、エスケープシーケンスを含めた文字列を送っていました。
SerialPortのリファレンスガイドを見ると、引数の指定をするとバイト配列を書き込むオーバーロードが呼び出されます。
つい文字列を書き込めば勝手にバイトに変換して書き込むだろうと認識していました。ここで誤った文字コードへの変換がされている可能性があるかもしれません。
頂いたコードとともに実機テストが終わり次第、記事更新させていただきます。

質問

  1. 他に試せそうなことはありますか
  2. VB.NETのString型はUTF-16とのこと、VB6.0と互換性の問題はあるでしょうか
  3. ラベラなどの機器でメーカー独自の文字コード表を使用している可能性はあるでしょうか

発生している問題・エラー・サンプル

送信データ
(略)4ONB030001D0000ス6シ000000000000

読み取りデータQR スマホ
(略)4ONB030001D0000?6?000000000000

自分で試したこと

・全角文字と同様に半角カナもShift-JISからJISへ変換を試みた→元のプログラムと同じバイトデータがコンソール出力できているが、ラベラにデータを送信して印字するとQRデータに反映されない
・エスケープシーケンス "ESC(I" を送信して半角カナの切り替えを試みた→エスケープシーケンス以降のデータが入らない
・ラベラ側の漢字変換文字コードをJIS→Shift-JISに変更→全角文字のみ文字化け、データ部の半角カナは?となる

ソースコード(半角カナ変換)

For i = 1 To psSiftJis.Length                   '桁数分繰り返す
        vHex = Hex(Asc(Mid(psSiftJis, i, 1)))   '1バイトのシフトJISコードに変換
        If vHex = "20" Then                     '空白なら抜ける
            vConv = Space(4)
            Exit For
        End If
        kByte = Val("&h" & vHex)                   '16→10進変換
        If kByte >= &H80 Then                       '半角カナのみShiftJIS→JIS変換
            kByte = kByte - &H80
            vConv = vConv & Chr(&H1B) & Chr(&H28) & Chr(&H49) & Chr("&h" & Hex(kByte)) '半角カナ開始エスケープシーケンス[ESC(I]
        Else
            vConv = vConv & Chr("&h" & Hex(kByte))
        End If
Next

実行環境

(以前)
Windows10
VB6.0

(更新後)
Windows10
VB.Net(.NET Framework4.7)
Visual Studio Professional 2017 version15.9.56

0 likes

4Answer

まずVB6とVB.NETで、送信直前のバイトデータを16進で出力してみて、そこが一致しているかどうかがスタートになると思います。
そこで一致するなら変換処理ではなく送信処理に問題がある、一致しないなら変換処理が間違っているこということになります。
どの処理で想定外のデータ変換が発生しているかを切り分けてください。

ラベラなどの機器でメーカー独自の文字コード表を使用している可能性はあるでしょうか

そのような事は仕様書を読むか、仕様書に記載がなければメーカーに直接問い合わせてください。(普通に考えて、記載がないとは考えにくいですが)

2Like

Comments

  1. @Kou1024

    Questioner

    コメントありがとうございます。
    文字列をASCII変換して、16進数にした出力はどちらも同じでした。
    元のプログラムでは、半角カナは変換をかけずに送信しています。(Shift-JIS)
    4E423033303030314430303030B632C0303030303030303030303030

  2. 文字列をASCII変換して、

    「ASCII変換」って何ですか?

    4E423033303030314430303030B632C0303030303030303030303030

    それの元の文字列はなんですか? 最初の質問に書いてあった、

    送信データ
    (略)4ONB030001D0000ス6シ000000000000

    ではないですよね?

  3. @Kou1024

    Questioner

    ASCII変換ではないですね。
    Asc関数で文字列1文字ずつに対応した文字コードを、Hex関数で16進数にしています。
    元の文字列はNB030001D0000カ2タ000000000000です。
    サンプル変えております。失礼いたしました。

  4. 私の回答の【追記】は読みましたか? そこでも書きましたが、そういう話ではないということでしたら、どこがやりたいことと違うのか書いてください。

  5. 文字列をASCII変換して、16進数にした出力はどちらも同じでした。
    元のプログラムでは、半角カナは変換をかけずに送信しています。(Shift-JIS)

    であれば、変換自体には問題はなく送信処理の問題だと思いますが。
    コンパイル可能な状態の送信処理のソースを載せてください。

  6. 質問の追記を確認しましたが、Stringとして送っているのであればSerialPortクラスのEncodingで変換されます。
    バイトデータのまま送信してください。

  7. @Kou1024

    Questioner

    皆様、ご回答ありがとうございました。解決いたしました。

    やったこと

    ・半角カナが含まれている文字列をShift-jisでエンコードしByte配列に格納
    ・SerialPortクラスのデータ送信メソッドをWrite(String)からWrite(Byte[], Int32, Int32)へ変更し、バイトデータを送信

    Shift-JISで変換したバイトコードをStringとして送っていたため、SerialPortクラスのEncodingで変換されてしまっていたようです。VB.NETのStringの文字コードはUTF-16で、半角カナの文字コードは127より大きいため?となっていたようです。

    全角文字をShift-JISからJISへ変換するコードがもともとあり、例えばJISに変換した全角$(0x2170)を、"2170"という文字列でラベラに送信して正しく印字されていたので、同様に送信したらいいと勘違いしておりました。

    ラベラの仕様も分からず、提示した情報も中途半端で、拙い文章で質問したこと、大変申し訳ありませんでした。参考となるご回答をいただき誠に感謝申し上げます。今後もこちらを使用させていただきたいと思いますが、回答者様に分かりやすく伝えられるよう精進いたします。

  8. 何で一番最初に私が聞いたことに答えなかったの? もう一回書くと、

    .NET アプリ内で "4ONB030001D0000ス6シ000000000000" という文字列を Shift_JIS のバイト列に変換できればいいのですか? 違うということなら何に変換できればいいのかを書いてください。

    そこをよく考えて、聞いてることが分からなかったら答えが出せるまで調べたら、何も分からないままいろいろ試して迷走して、それに回答者を巻き込む前に解決できたはず。

    VB.NETのStringの文字コードはUTF-16で、半角カナの文字コードは127より大きいため?となっていたようです。

    「VB.NETのStringの文字コードはUTF-16で、半角カナの文字コードは127より大きい」というのは全くの見当違いです。質問者の知識不足で話が通じてないというのが今回のやり取りの一番の問題だったようです。次回質問する際は、話が通じる程度には事前に調べて知識をつけていただくようお願いします。

  9. 解決されたようで良かったです。
    知識不足でうまく伝えられない、ということはあるとは思いますが、問題解決の基本は「問題の発生している箇所の切り分け」です。データが化ける、というのが分かっているのであれば、各処理の結果をログに出力したりして正しいデータと比較して、どこまで処理が正しく動いているか検証するのは特に知識が無くても出来ますよね。病院行ったときに、体のどこがどう調子が悪いのか具体的に医者に伝えますよね?それと同じことです。
    事前にそういったデータが提示されていれば、回答者も原因の推測がしやすいのでスムーズに解決すると思います。

This answer has been deleted for violation of our Terms of Service.

.NET アプリ内で "4ONB030001D0000ス6シ000000000000" という文字列を Shift_JIS のバイト列に変換できればいいのですか? 違うということなら何に変換できればいいのかを書いてください。


【追記】

送信データの問題っぽいです

シリアル通信ということだそうなので「送信データ」は文字列をバイト列に変換したもので、そのバイト列が問題ということと理解します。

そして、

全角文字はShift-JISからJISへの変換をしていたので

・・・の「JIS」というのはたぶん ↓ これのことであろうと想像して、

csISO2022JP.jpg

"4ONB030001D0000ス6シ000000000000" という文字列を「Shift_JIS」および「csISO2022JP 日本語(jis 1 バイト カタカナ可)」のバイト列に変換するサンプルコードを書いておきます。

Imports System.Text

Module Module1

    Sub Main()
        Dim str As String = "4ONB030001D0000ス6シ000000000000"

        Dim sjis As Encoding = Encoding.GetEncoding("shift_jis")
        Dim sjisBytes As Byte() = sjis.GetBytes(str)
        For Each b As Byte In sjisBytes
            Console.Write($"[{b:X}]")
        Next

        Console.WriteLine("--------------------------------------------")

        'csISO2022JP 日本語(jis 1 バイト カタカナ可)
        Dim jis As Encoding = Encoding.GetEncoding("csISO2022JP")
        Dim jisBytes As Byte() = jis.GetBytes(str)
        For Each b As Byte In jisBytes
            Console.Write($"[{b:X}]")
        Next
    End Sub

End Module

'結果は:
'[34][4F][4E][42][30][33][30][30][30][31][44][30][30][30][30]
'[BD][36][BC]
'[30][30][30][30][30][30][30][30][30][30][30][30]
'--------------------------------------------
'[34][4F][4E][42][30][33][30][30][30][31][44][30][30][30][30]
'[1B][28][49][3D][1B][28][42][36][1B][28][49][3C][1B][28][42]
'[30][30][30][30][30][30][30][30][30][30][30][30]
'
'ス6シ の前後に改行を入れてます

こういう話ではないということでしたら、どこがやりたいことと違うのか書いてください。


【追記2】

今質問の追記に気が付きました。

現在は、コード内で
SerialPort1.Write(str)
として、エスケープシーケンスを含めた文字列を送っていました。
SerialPortのリファレンスガイドを見ると、引数の指定をするとバイト配列を書き込むオーバーロードが呼び出されます。つい文字列を書き込めば勝手にバイトに変換して書き込むだろうと認識していました。ここで誤った文字コードへの変換がされている可能性があるかもしれません。

「SerialPortのリファレンスガイド」に "既定では、 SerialPort を使用 ASCIIEncoding して文字をエンコードします。 ASCIIEncoding は、127 より大きいすべての文字を (char)63 または '?' としてエンコードします" と書いてあるのに気が付きませんでしたか?

で、結局どうしたいのですか? 何回聞いてもストレートな答えが返ってきませんが、もう一回聞きます。

.NET アプリ内で "4ONB030001D0000ス6シ000000000000" という文字列を Shift_JIS のバイト列に変換できればいいのですか? 違うということなら何に変換できればいいのかを書いてください。

1Like

Comments

  1. @Kou1024

    Questioner

    コメントありがとうございます。
    全角文字はShift-JISからJISへの変換をしていたので、同様に半角カナもJISのバイト列に変換して送信したつもりですが、正しく表示されないという状況です。
    JISで半角カナを使用する際はエスケープシーケンスで切り替える必要があると記述されており、それを送信したのですが変換はされずでした。
    変換に問題があるかどうか、送信前のデータを16進で表示させてみます。

日本語対応QRコードリーダーを使用する必要があると思われます。


ちなみに、iPhoneSE3のカメラで4ONB030001D0000ス6シ000000000000の下記QRコードを読み取ると、4ONB030001D0000½6¼000000000000となりましが、

QR_973548.png

試しに、↓こちらのアプリで読み取ると、4ONB030001D0000ス6シ000000000000となりました。

1Like

Comments

  1. @Kou1024

    Questioner

    コメントありがとうございます。
    普段はキーエンスのリーダーで読みますが、iPhoneSEでテスト読み取りをしておりました。
    アプリインストールしても半角カナが?になってしまいました。
    元のラベルは問題なく半角カナが読み取りできています。
    送信データの問題っぽいです

  2. 送信データの問題っぽいです

    シリアル通信ということだそうなので「送信データ」は文字列をバイト列に変換したものですよね。で、そのバイト列が問題ということですよね? であれば、上でも聞きましたが、

    .NET アプリ内で "4ONB030001D0000ス6シ000000000000" という文字列を Shift_JIS のバイト列に変換できればいいのですか? 違うということなら何に変換できればいいのかを書いてください。

    ・・・に答えていただけませんか?

  3. 送信データの問題っぽいです

    「VB6の時と同じ16進データが作れていない」ということだと想定しました。
    印刷装置側でShift-JISに変更できるのなら、漢字も半角カナもShift-JISにしてしまうのが、一番楽だと思います。

Your answer might help someone💌