(Java)字符'é';JTextArea中的显示错误

(Java)字符'é';JTextArea中的显示错误,java,string,swing,encoding,jtextarea,Java,String,Swing,Encoding,Jtextarea,第一次发布一些东西,我有一个问题 我使用JFrame和JTextArea,将控制台输出重定向到JTextArea。在控制台中,它正确显示。这是重定向的代码: public PrintStream redirectOut() { OutputStream out = new OutputStream() { @Override public void write(int b) throws IOException {

第一次发布一些东西,我有一个问题

我使用JFrame和JTextArea,将控制台输出重定向到JTextArea。在控制台中,它正确显示。这是重定向的代码:

public PrintStream redirectOut() {
    
    OutputStream out = new OutputStream() {
        @Override
        
        public void write(int b) throws IOException {
            String k = String.valueOf((char) b);
            byte[] o = k.getBytes();
            String text = new String(o,"Cp1252");
            output.append(k);
        }
    };
    PrintStream ps = new PrintStream(out);
    System.setOut(ps);
    System.setErr(ps);
    return ps;
}
如果我将字符“é”以相同的方式放入文本区域,它将正确显示,但不是这样。为什么呢?有人有办法吗?(输出是我的JTextArea)
谢谢

不太清楚您的多步骤转换想要实现什么

由于某些原因,
write(int)
方法将接收单个
字节
,作为
int
传递。由于字节源于构造为新打印流(out)的
打印流
,因此它将以系统的默认编码进行编码

使用相同(系统默认)编码将其转换回
字符串的一种方法是

byte[]数组={(byte)b};
字符串文本=新字符串(数组);
然而,有一些事情需要记住

  • 系统默认编码可能不支持所有unicode字符。因此,上面的代码是正确的,但仍可能导致数据丢失。因此,您不应依赖于系统默认编码,而应使用能够处理所有字符的显式编码,例如UTF-8,用于两侧

  • 这种方法无法处理多字节编码,因为当尝试将多字节序列中的单个字节转换回字符串时,最终将得到无效或错误的字符。便携式程序不能假定知道系统默认编码是否为多字节。当遵循第1点的建议时,您将始终以多字节编码结束。您需要一种在将字节转换为字符串之前可以累积多个字节的解决方案。这甚至可以提高效率

  • 以下是一个完整的解决方案:

    公共类PrintToTextArea通过tearrayoutputstream扩展实现Runnable
    {
    公共静态打印流创建(JTextArea ta)
    {
    尝试
    {
    返回新的PrintStream(新的PrintToTextArea(ta),true,“UTF-8”);
    }
    捕获(不支持DencodingException ex)
    {
    抛出新断言错误(“应始终支持UTF-8”,例如);
    }
    }
    私人区域目标;
    私有PrintToTextArea(JTextArea ta)
    {
    超级(100);
    目标=ta;
    }
    @凌驾
    公共图书馆
    {
    if(EventQueue.isDispatchThread())run();else EventQueue.invokeLater(this);
    }
    @凌驾
    公共同步的无效运行()
    {
    append(新字符串(buf,0,count,StandardCharsets.UTF_8));
    计数=0;
    }
    }
    
    它在两侧使用UTF-8来处理所有unicode字符,并在
    ByteArrayOutputStream
    的缓冲区中收集字节,以创建新的
    字符串
    ,并在调用
    flush
    时追加它,这会在换行或显式调用
    flush
    时自动发生

    你可以试试这样的东西

    publicstaticvoidmain(字符串[]args){
    请尝试{UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());}
    catch(ReflectiveOperationException | UnsupportedLookAndFeelException ex){}
    JFrame f=新的JFrame();
    JTextArea ta=新的JTextArea(40,60);
    f、 setContentPane(新的JScrollPane(ta));
    PrintStream ps=PrintToTextArea.create(ta);
    系统放样(ps);
    系统设置错误(ps);
    f、 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f、 包装();
    f、 setVisible(真);
    锁支持。Parknos(时间单位。秒。toNanos(1));
    Thread.dumpStack();
    系统输出打印项次(“È”);
    锁支持。Parknos(时间单位。秒。toNanos(1));
    系统输出打印;
    锁支持。Parknos(时间单位。秒。toNanos(1));
    System.out.println(“\u263a\ud83d\ude80”);
    锁支持。Parknos(时间单位。秒。toNanos(1));
    }
    
    不太清楚您的多步骤转换想要实现什么

    由于某些原因,
    write(int)
    方法将接收单个
    字节
    ,作为
    int
    传递。由于字节源于构造为新打印流(out)
    打印流
    ,因此它将以系统的默认编码进行编码

    使用相同(系统默认)编码将其转换回
    字符串的一种方法是

    byte[]数组={(byte)b};
    字符串文本=新字符串(数组);
    
    然而,有一些事情需要记住

  • 系统默认编码可能不支持所有unicode字符。因此,上面的代码是正确的,但仍可能导致数据丢失。因此,您不应依赖于系统默认编码,而应使用能够处理所有字符的显式编码,例如UTF-8,用于两侧

  • 这种方法无法处理多字节编码,因为当尝试将多字节序列中的单个字节转换回字符串时,最终将得到无效或错误的字符。便携式程序不能假定知道系统默认编码是否为多字节。当遵循第1点的建议时,您将始终以多字节编码结束。您需要一种在将字节转换为字符串之前可以累积多个字节的解决方案。这甚至可以提高效率

  • 以下是一个完整的解决方案:

    公共类PrintToTextArea通过tearrayoutputstream扩展实现Runnable
    {
    公共静态打印流创建(JTextArea ta)
    {
    尝试
    {
    返回新的PrintStream(新的PrintToTextArea(ta),true,“UTF-8”);
    }
    捕获(不支持DencodingException ex)
    {
    抛出新断言错误(“应始终支持UTF-8”,例如);
    }
    }
    私人区域目标;
    私有PrintToTextArea(JTextArea ta)
    {
    超级(100);
    目标=ta;
    }
    @凌驾
    公共图书馆
    {
    if(EventQueue.isDispatchThread())run();else EventQueue.invokeLater(this);
    }
    @凌驾
    公共同步的无效运行()
    {