10

ターミナルエミュレータライブラリを使用してターミナルを作成し、それを使用して、シリアルで入力されたデータをシリアルデバイスに送信します。ライブラリはここで見ることができます。

端末にデータを入力すると、奇妙な一連の文字が送受信されます。Unicode置換文字はシリアル経由で送信されると思いますが、シリアルデバイスはそれが何であるかを認識せず、〜0を返します。

「test」と書いたときにターミナルに表示されるスクリーンショット:ここに画像の説明を入力してください

そして、送信された文字列と受信されたデータを示すログ。http://i.imgur.com/x79aPzv.png

EmulatorViewを作成します。これはターミナルビューです。ここでダイヤモンドについて言及しています。

private void sendText(CharSequence text) {
                int n = text.length();
                char c;
                try {
                    for(int i = 0; i < n; i++) {
                        c = text.charAt(i);
                        if (Character.isHighSurrogate(c)) {
                            int codePoint;
                            if (++i < n) {
                                codePoint = Character.toCodePoint(c, text.charAt(i));
                            } else {
                                // Unicode Replacement Glyph, aka white question mark in black diamond.
                                codePoint = '\ufffd';
                            }
                            mapAndSend(codePoint);
                        } else {
                            mapAndSend(c);
                        }
                    }
                } catch (IOException e) {
                    Log.e(TAG, "error writing ", e);
                }
            }

これを修正する方法はありますか?なぜこれが起こっているのかをライブラリクラスで誰かが見ることができますか?、Javaで�を参照して、必要に応じて解析することもできますか?(!str.contains( "�")私がそれを取るかどうかは言えません。

ターミナルに入力すると、これが実行されます。

public void write(byte[] bytes, int offset, int count) {


 String str;
try {
    str = new String(bytes, "UTF-8");
      Log.d(TAG, "data received in write: " +str );

      GraphicsTerminalActivity.sendOverSerial(str.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
    Log.d(TAG, "exception" );
    e.printStackTrace();
}

        // appendToEmulator(bytes, 0, bytes.length);

 return;
}

これは私がデータを送信するために呼び出すものです。sendData(Byte [] data)はライブラリメソッドです。

public static void sendOverSerial(byte[] data) {
        String str;
        try {
            str = new String(data,"UTF-8");
             if(mSelectedAdapter !=null && data !=null){
                 Log.d(TAG, "send over serial string==== " + str);

                mSelectedAdapter.sendData(str.getBytes("UTF-8"));
                 }
        } catch (UnsupportedEncodingException e) {
            Log.d(TAG, "exception");
            e.printStackTrace();
        }

    }

データが送信されると、ここで応答が受信されます。

public void onDataReceived(int id, byte[] data) {

        try {
            dataReceived = new String(data, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            Log.d(TAG, "exception");
            e.printStackTrace();
        }

        try {
            dataReceivedByte = dataReceived.getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            Log.d(TAG, "exception");
            e.printStackTrace();
        }
        statusBool = true;
        Log.d(TAG, "in data received " + dataReceived);
        ((MyBAIsWrapper) bis).renew(data);


        runOnUiThread(new Runnable(){

            @Override
            public void run() {

                mSession.appendToEmulator(dataReceivedByte, 0, dataReceivedByte.length);

            }});

    viewHandler.post(updateView);

}

文字が書き込まれるライブラリクラスの関連セクション:

クラスの関連セクション:

private void sendText(CharSequence text) {
                int n = text.length();
                char c;
                try {
                    for(int i = 0; i < n; i++) {
                        c = text.charAt(i);
                        if (Character.isHighSurrogate(c)) {
                            int codePoint;
                            if (++i < n) {
                                codePoint = Character.toCodePoint(c, text.charAt(i));
                            } else {
                                // Unicode Replacement Glyph, aka white question mark in black diamond.
                                codePoint = '\ufffd';
                            }
                            mapAndSend(codePoint);
                        } else {
                            mapAndSend(c);
                        }
                    }
                } catch (IOException e) {
                    Log.e(TAG, "error writing ", e);
                }
            }

            private void mapAndSend(int c) throws IOException {
                int result = mKeyListener.mapControlChar(c);
                if (result < TermKeyListener.KEYCODE_OFFSET) {
                    mTermSession.write(result);
                } else {
                    mKeyListener.handleKeyCode(result - TermKeyListener.KEYCODE_OFFSET, getKeypadApplicationMode());
                }
                clearSpecialKeyStatus();
            }
4

3 に答える 3

1

Javaは、テキストをエンコードされていないUnicodeとして内部に格納します。以前は16ビットでしたが、出力しようとしているUnicode文字ごとに端末で4文字の出力が得られるという事実に基づいて、32ビットだと推測しています。

おそらくやりたいことは、string.getBytes( "ASCII")のようなものを使用して、Unicode文字列をストレートのシングルバイトASCIIに変換することです。ターミナルエミュレータが他の文字セット(Latin-1など)を処理する場合は、「ASCII」の代わりにそれを使用してください。

次に、文字列の代わりにバイトをターミナルエミュレータに送信します。

注:「ASCII」が文字セットの正確な名前であるとは思いません。あなたはそれを自分で研究したいと思うでしょう。また、getBytes()がASCIIに変換できないUnicode文字で何をするのかわからないので、それも調べてみてください。

ETA:投稿したスクラップからコードロジックを追跡するのに問題があります。誰がwrite()を呼び出し、データはどこから来て、どこに行くのですか?同じ質問がsendOverSerial()とonDataReceived()にも当てはまります。

いずれにせよ、私はどこかで、生の32ビットUnicodeデータがエンコードされずにバイトに変換されたことをほぼ確信しています。その時点から、そのまま送信するか、UTF-8として再エンコードすると、表示されている効果が得られます。あなたが投稿したコードでこれがどのように起こったのかわかりません。そのため、あなたが示した関数が呼び出される前に、他の場所で起こったと思います。

于 2013-01-25T16:26:56.100 に答える
0

使用しているライブラリを編集することで、この問題を解決しました。彼らはバイトをintに変換するメソッドを使用していました。それはcodePointを受け入れ、それを変換しました。したがって、キーを押すたびに4バイトが使用されます。これを変更して、intの代わりにバイトが使用されるようにしました。これ以上余分なバイトはありません。エンコーディング形式とは何の関係もありません。

于 2013-01-30T11:53:05.277 に答える
0

使用しているライブラリはコードポイントをint(32ビット)として送信しており、コードは4バイトを適切に処理しないutf-8としてエンコードされていると想定しているようです。これは、Javaがテキストを内部的に保存する方法とは関係ありません。ところで、Javaは、エンコードされていないUnicodeではなく、エンコードされたUTF-16としてテキストを内部に格納します。繰り返しますが、これはこの問題の原因ではありません。これは、使用しているライブラリとのやり取りの方法です。

于 2013-02-01T19:28:07.917 に答える