6

バイト ストリームを UTF-8 文字の行に変換する必要があります。その行で私にとって重要な唯一の文字は、最後の文字です. そして、この変換はサイクルで発生する必要があるため、パフォーマンスは非常に重要です。単純で非効率的なアプローチは次のとおりです。

public class Foo {
  private ByteArrayOutputStream buffer = new ByteArrayOutputStream();
  void next(byte input) {
    this.buffer.write(input);
    String text = this.buffer.toString("UTF-8"); // this is time consuming
    if (text.charAt(text.length() - 1) == THE_CHAR_WE_ARE_WAITING_FOR) {
      System.out.println("hurray!");
      this.buffer.reset();
    }   
  }
}

バイト配列から文字列への変換は、入力バイトごとに発生しますが、これは私の理解では非常に効果的ではありません。前のサイクルからのバイトからテキストへの変換の結果を保存するために、他の方法でそれを行うことは可能ですか?

4

4 に答える 4

6

単純なクラスを使用して文字を追跡し、完全な UTF8 シーケンスを取得したときにのみ変換できます。これがサンプルです(追加したいエラーチェックはありません)

class UTF8Processor {
    private byte[] buffer = new byte[6];
    private int count = 0;

    public String processByte(byte nextByte) throws UnsupportedEncodingException {
        buffer[count++] = nextByte;
        if(count == expectedBytes())
        {
            String result = new String(buffer, 0, count, "UTF-8");
            count = 0;
            return result;
        }
        return null;
    }

    private int expectedBytes() {
        int num = buffer[0] & 255;
        if(num < 0x80) return 1;
        if(num < 0xe0) return 2;
        if(num < 0xf0) return 3;
        if(num < 0xf8) return 4;
        return 5;
    }
}

class Bop
{
    public static void main (String[] args) throws java.lang.Exception
    {
        // Create test data.
        String str = "Hejsan åäö/漢ya";
        byte[] bytes = str.getBytes("UTF-8");

        String ch;

        // Processes byte by byte, returns a valid UTF8 char when 
        //there is a complete one to get.

        UTF8Processor processor = new UTF8Processor();

        for(int i=0; i<bytes.length; i++)
        {
            if((ch = processor.processByte(bytes[i])) != null)
                System.out.println(ch);
        }
    }
}
于 2013-06-23T07:20:31.677 に答える
2

コメントに基づいて:

改行です(0x0A)

メソッドnextは次のことを確認できます。

if ((char)input == THE_CHAR_WE_ARE_WAITING_FOR) {
    //whatever your logic is.
}

文字数が 128 未満の場合は、変換する必要はありません。

于 2013-06-23T07:23:27.253 に答える
1

次の 2 つのオプションがあります。

  • 関心のあるコードポイントが (UTF-8 用語で) 128 未満のコードポイントのような単純なものである場合は、からbyteへの単純なキャストcharが可能です。これが機能する理由については、Wikipadia: UTF-8でエンコーディング規則を参照してください。

  • これが不可能な場合はCharset、Java のエンコード/デコード ライブラリのルートであるクラスを調べることができます。CharsetDecoderここでは、N バイトをフィードして M 文字を返すことができるものを見つけます。一般的なケースは N != M です。ただし、 と に対処する必要がByteBufferありCharBufferます。

于 2013-06-23T07:23:16.930 に答える