Java IO小结

IO体系继承图

两个进程间通过网络传输字符串

在计算机底层传输的只有形如01011101这种数字,1字节是由8位bit组成,而字符则是在某种字符集下字节的表现形式,最终都是通过一串01数字表达。当我们谈论字符而忽略字符集时是完全没有意义的,之所以有时不用去关心字符集是因为平台往往是有个默认的字符集。所以在传输字符的时候,发送方和接收方必须要事先约定好字符集。

下面的例子摘自《Java特种兵》书籍的第四章

例如发送2个汉字,用UTF-8编码发送后会占用6个字节,对方若知道传来的数据是UTF-8编码,便知道这6个字节代表什么汉字,就自然能正确得到char字符了。但是如果对方用GBK来编码,则可能会认为有3个字符,若按照每2个字节计算一个字符,得到的3个字符自然不是需要传递的2个汉字字符。假如此时意识到自己的编码错误了,通过得到的3个字符的字符串调用get-Byte(“GBK”)还可以还原6个字节,然后通过这6个字节再用new String(byte[],“UTF-8”)得到实际的两个汉字。真的是这样吗?要知道这是偶然的,不是必然的,因为UTF-8转换出来的6个字节,当按照每2个字节组成编码时,这个编码未必在GBK的编码范围内,若不在GBK的编码范围内,就可能会用一个“?”或其他字符来代表,由于“?”本身也是一个字符,当再次调用get-Byte(“GBK”)时得到的对应字节就是“?”对应的字节,而不是原来字符的字节,有可能都不再是6个字节了。换句话说,这样的情况是永远无法转换回来的。

字节流和字符流的关系
Reader/Writer内在的实现是通过sun.nio.cs.StreamDecoder、sun.nio.cs.StreamEn-coder来对字符集进行处理,最终还是通过字节来完成发送和接收的。

read()的小疑惑

InputStream.read()方法返回一个int值,表示从流中读取的一个字节。我们知道byte类型的取值范围是:-128到127,但是read方法返回值的范围是0 - 255(另外返回-1表示流中没有可读字节)。
为什么要这样设计呢?其中一个原因是因为字符集的码表都是用非负数来表示的。
那如何进行转换呢?在BufferedInputStream中,其read()方法是这样写的

public synchronized int read() throws IOException {
    if (pos >= count) {
        fill();
        if (pos >= count)
            return -1;
    }
    return buf[pos++] & 0xff;
}

其中buf是byte数组,可以看到通过buf[pos++] & 0xff将字节的范围转移到0 - 255。

按用途分类流

字节输入流 字节输入流 字符输入流 字符输出流
基础 InputStream OutputStream Reader InputStreamReader Writer OutputStreamWriter
数组 ByteArrayInputStream ByteArrayOutputStream CharArrayReader CharArrayWriter
文件 FileInputStream RandomAccessFile FileOutputStream RandomAccessFile FileReader FileWriter
网络 SocketInputStream URL HttpURLConnection Socket SocketOutputStream URL HttpURLConnection Socket
管道 PipedInputStream PipedOutputStream PipedReader PipedWriter
缓冲 BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter
Filtering FilterInputStream FilterOutputStream FilterReader FilterWriter
解析 PushbackInputStream StreamTokenizer PushbackReader LineNumberReader
String StringReader StringWriter
Data DataInputStream DataOutputStream
格式 PrintStream PrintWriter
序列化 ObjectInputStream ObjectOutputStream
Utilities SequenceInputStream LineNumberInputStream LineNumberReader

扩展阅读
Java IO Tutorial

你可能感兴趣的:(Java IO小结)