Java 如何将字节流转换为UTF-8字符?

Java 如何将字节流转换为UTF-8字符?,java,utf-8,character-encoding,Java,Utf 8,Character Encoding,我需要将字节流转换为UTF-8字符行。在这一行中,对我来说唯一重要的角色是最后一个。这种转换应该在一个周期内进行,所以性能非常重要。一种简单而低效的方法是: public class Foo { private ByteArrayOutputStream buffer = new ByteArrayOutputStream(); void next(byte input) { this.buffer.write(input); String text = this.buf

我需要将字节流转换为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();
    }   
  }
}

字节数组到字符串的转换发生在每个输入字节上,据我所知,这是非常无效的。是否可以以其他方式保存上一个周期的字节到文本转换结果?

将字节获取代码包装在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(); 
        }
    }

您可以使用一个简单的类来跟踪字符,并且只有在获得完整的UTF8序列时才能进行转换。这是一个示例(您可能希望添加没有错误检查的示例)

类UTF8处理器{
专用字节[]缓冲区=新字节[6];
私有整数计数=0;
公共字符串processByte(byte nextByte)引发不支持的编码异常{
缓冲区[count++]=nextByte;
如果(计数==expectedBytes())
{
字符串结果=新字符串(缓冲区,0,计数,“UTF-8”);
计数=0;
返回结果;
}
返回null;
}
私有int expectedBytes(){
int num=缓冲区[0]&255;
如果(num<0x80)返回1;
如果(num<0xe0)返回2;
if(num<0xf0)返回3;
如果(num<0xf8)返回4;
返回5;
}
}
防喷器类
{
公共静态void main(字符串[]args)引发java.lang.Exception
{
//创建测试数据。
String str=“Hejsanåäö/漢"雅",;
byte[]bytes=str.getBytes(“UTF-8”);
弦ch;
//逐字节处理,在以下情况下返回有效的UTF8字符:
//有一个完整的。
UTF8Processor=新的UTF8Processor();
对于(int i=0;i您有两个选项:

  • 如果您感兴趣的代码点是简单的(UTF-8术语)代码点,即128以下的代码点,则可以从
    字节
    字符
    进行简单转换。查找上的编码规则以了解其工作原因

  • 如果这是不可能的,您可以查看
    Charset
    类,它是Java编码/解码库的根。在这里您可以找到
    CharsetDecoder
    ,您可以输入N个字节并返回M个字符。一般情况下是N!=M。但是您必须处理
    ByteBuffer
    CharBuffer

根据评论:

它是换行符(0x0A)

您的
next
方法只需检查:

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

您不必对<128个字符进行任何转换。

我这里缺少一些东西。当UTF-8文本每个字符使用超过一个字节时,您如何转换单个字节?这就是为什么我需要一个
ByteArrayOutputStream
来完成此转换任务。为什么不使用InputStreamReader?但您仍然只读取单个字节ng转换甚至可能在不完整字符/上失败,因为没有可读取的流,如您在示例中所看到的请参阅对我的问题的更新。我不能等待字节..它们是从其他地方注入到我的类中的。换句话说,我不能停留并等待下一个字节,就像在您的example@yegor256你现在编辑的问题是:t与原始问题根本不同。编辑问题的两个选项是使用带有专用线程的InputStreamReader来等待数据,或实现有状态UTF-8解码器。UTF-8序列的长度最大为4,长度可以通过检查第一个字节来确定。一旦每个序列都被删除您可以放弃它,而不是像代码那样缓冲整个输入流(您意识到这是低效的)-没有充分的理由要求从外部管理缓冲区。@Clyde True,这不是几分钟内抛出的最干净的代码。不过我会解决这个问题。
if ((char)input == THE_CHAR_WE_ARE_WAITING_FOR) {
    //whatever your logic is.
}