如何从PrintStream字节编码中恢复?

时间:2015-03-26 15:54:42

标签: java encoding

最新的SSCCEE

为什么以下示例会输出不同的字符串?

package tests.java;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.nio.charset.Charset;
import java.util.Arrays;

public class Try_PrintWriterEncoding3 {

    public static void main(String[] args) {
        final PrintStream oldOut = System.out;

        System.out.println("Привет, мир!");

        System.setOut(new PrintStream(new OutputStream() {

            @Override
            public void write(int b) throws IOException {
                oldOut.print(new String(new byte[] {(byte)b}, Charset.defaultCharset())); 
            }
        }));

        System.out.println("Привет, мир!");

        System.setOut(new PrintStream(new OutputStream() {

            @Override
            public void write(int b) throws IOException {
                throw new UnsupportedOperationException(); 
            }

            @Override
            public void write(byte[] b, int off, int len) throws IOException {
                oldOut.print(new String(Arrays.copyOf(b, len), Charset.defaultCharset()));
            }

            @Override
            public void write(byte[] b) throws IOException {
                throw new UnsupportedOperationException(); 
            }
        }));

        System.out.println("Привет, мир!");
    }
}

以前的示例

我想编写自定义标准输出流,但使用国际编码失败。

据说,PrintStream根据默认编码将字符转换为字节。这可能意味着要解码,也应该使用默认编码。

但它没有用。

此外,任何其他可能的编码都无法正常工作。

package tests.java;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

import java.nio.charset.Charset;

public class Try_PrintWriterEncoding {

    public static void main(String[] args) {

        final PrintStream oldOut = System.out;

        System.out.println("Привет, мир!");

        System.setOut(new PrintStream(new OutputStream() {

            @Override
            public void write(int b) throws IOException {
                oldOut.write(b); // works
            }
        }));

        System.out.println("Привет, мир!");

        System.setOut(new PrintStream(new OutputStream() {

            @Override
            public void write(int b) throws IOException {
                oldOut.print(new String(new char[] {(char)b})); // does not work (garbage type 1)
            }
        }));

        System.out.println("Привет, мир!");

        System.setOut(new PrintStream(new OutputStream() {

            @Override
            public void write(int b) throws IOException {
                oldOut.print(new String(new byte[] {(byte)b})); // does not work (garbage type 2)

            }
        }));

        System.out.println("Привет, мир!");

        System.setOut(new PrintStream(new OutputStream() {

            @Override
            public void write(int b) throws IOException {
                oldOut.print(new String(new byte[] {(byte)b}, Charset.defaultCharset())); // does not work (garbage type 2)
            }
        }));

        System.out.println("Привет, мир!");

        System.setOut(new PrintStream(new OutputStream() {

            @Override
            public void write(int b) throws IOException {
                oldOut.print(new String(new byte[] {(byte)b}, Charset.forName("UTF-8"))); // does not work (garbage type 2)
            }
        }));

        System.out.println("Привет, мир!");


        System.setOut(new PrintStream(new OutputStream() {

            @Override
            public void write(int b) throws IOException {
                oldOut.print(new String(new byte[] {(byte)b}, Charset.forName("CP866"))); // does not work (garbage type 3)
            }
        }));

        System.out.println("Привет, мир!");

        System.setOut(new PrintStream(new OutputStream() {

            @Override
            public void write(int b) throws IOException {
                oldOut.print(new String(new byte[] {(byte)b}, Charset.forName("Cp1251"))); // does not work (garbage type 4)
            }
        }));

        System.out.println("Привет, мир!");
    }
}

输出

enter image description here

1 个答案:

答案 0 :(得分:1)

更改

 }));

 }), true, encoding);

其中true表示在换行符上刷新,并根据需要进行编码,例如“Windows-1251”。

它永远不会用于真实的控制台,因为它是操作系统定义的。

否则你必须假装一个控制台,就像IDE一样。或者确保控制台(cmd.exe)为run under Unicode or so


  System.setOut(new PrintStream(new OutputStream() {

        byte[] line = new byte[1024];
        int pos = 0;

        @Override
        public void write(int b) throws IOException {
            line[pos++] = (byte) b;
            if (pos >= line.length || b == '\n') {
                flush();
            }
        }

        @Override
        public void flush() throws IOException {
            oldOut.println(new String(line, 0, pos, ENCODING));
            oldOut.flush();
            pos = 0;
        }
    }), true, encoding);

首先尝试不提供ENCODING,默认为操作系统的。