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

你有两个选择:

  • 如果您感兴趣的代码点很简单(以 UTF-8 术语表示)为低于 128 的代码点,则可以进行简单的从bytetochar转换。在Wikipadia: UTF-8上查找编码规则以了解其工作原理。

  • 如果这不可能,您可以查看Charset作为 Java 编码/解码库的根的类。在这里你会发现CharsetDecoder你可以输入 N 个字节并取回 M 个字符。一般情况是 N != M 。但是,您将不得不处理ByteBufferand CharBuffer

于 2013-06-23T07:23:16.930 回答
0

将获取字节的代码包装在 InputStream 中并将其传递给 InputStreamReader。

    InputStreamReader isr = new InputStreamReader(new InputStream() {
        @Override
        public int read() throws IOException {
            return xx();// wherever you get your data from.
        }
    }, "UTF-8");
    while(true) {
        try {
            if(isr.read() == THE_CHAR_WE_ARE_WAITING_FOR)
                System.out.println("hurray!");
        } catch(IOException e) {
            e.printStackTrace(); 
        }
    }
于 2013-06-23T07:01:16.177 回答