Java Oracle网站中字符流示例代码的混淆

Java Oracle网站中字符流示例代码的混淆,java,Java,当我从中读取以下内容时,我从inputStream.read() 那么它总是浪费2个字节吗 CopyCharacters与CopyBytes非常相似。最重要的 不同之处在于CopyCharacters使用FileReader和FileWriter来 输入和输出代替FileInputStream和FileOutputStream。 请注意,CopyBytes和CopyCharacters都使用int变量 读和写。但是,在CopyCharacters中,int变量 保存最后16位的字符值;在Copy

当我从中读取以下内容时,我从
inputStream.read()

那么它总是浪费2个字节吗

CopyCharacters与CopyBytes非常相似。最重要的 不同之处在于CopyCharacters使用FileReader和FileWriter来 输入和输出代替FileInputStream和FileOutputStream。 请注意,CopyBytes和CopyCharacters都使用int变量 读和写。但是,在CopyCharacters中,int变量 保存最后16位的字符值;在CopyBytes中,int 变量在其最后8位中保存一个字节值

那么它总是浪费2个字节吗

嗯。。。对
读取器
案例中的2个字节或
输入流
案例中的3个字节

这种浪费是必要的,原因如下:

  • InputStream.read()
    Reader.read()
    都需要返回一个值来表示“流的结束”。正如javadocs所说:

    InputStream.read()
    :从输入流读取数据的下一个字节。值字节作为0到255范围内的整数返回。如果由于到达流的结尾而没有字节可用,则返回值-1

    Reader.read()
    :返回读取的字符,作为0到65535(0x00-0xffff)范围内的整数,如果已到达流的结尾,则返回-1

    额外的流结束值意味着
    read()
    的返回类型不能(分别)为
    byte
    char
    。(另见最后一个原因…)

  • 事实证明,“浪费”的2或3个字节是无关紧要的。即使是一个微不足道的Java程序也将使用兆字节的内存。(事实上,即使是一个微不足道的C程序也将使用数十或数百KB的内存……如果您考虑到它们使用的库代码的话。)

  • 返回
    字节
    字符
    可能不会节省内存。在典型的现代系统中,局部变量(甚至
    byte
    char
    )以字对齐的方式存储在堆栈上。这样做是因为使用字对齐地址访问内存通常更快

  • 用异常替换
    -1
    ,在另一方面效率低下。在Java中抛出和捕获异常比对
    -1
    进行简单测试要昂贵得多


  • 我可能弄错了,但我相信如果您使用32位编码作为默认编码,例如UTF-32,这会很有用。@Aaron-
    Reader.read()
    将返回UTF-16代码单元(或-1),而不管您正在读取的流的编码是什么。这就是
    阅读器的全部要点。它将输入编码解码为标准表示法:UTF-16表示法中的Unicode代码点。@StephenC说得通,谢谢你纠正我。谢谢你上面的回答,特别是第3点和第4点。
    
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    
    public class CopyCharacters {
        public static void main(String[] args) throws IOException {
    
            FileReader inputStream = null;
            FileWriter outputStream = null;
    
            try {
                inputStream = new FileReader("xanadu.txt");
                outputStream = new FileWriter("characteroutput.txt");
    
                int c;
                while ((c = inputStream.read()) != -1) {
                    outputStream.write(c);
                }
            } finally {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
            }
        }
    }