IO相关类关系图
输入
字节流
InputStream
package java.io;
public abstract class InputStream implements Closeable {
private static final int MAX_SKIP_BUFFER_SIZE = 2048;
public abstract int read() throws IOException;
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
/* Reads the next byte of data from the input stream. */
public int read(byte b[], int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
int c = read();
if (c == -1) { return -1; }
b[off] = (byte)c;
int i = 1;
try {
for (; i < len ; i++) {
c = read();
if (c == -1) {
break;
}
b[off + i] = (byte)c;
}
} catch (IOException ee) { }
return i;
}
public long skip(long n) throws IOException {
//...
}
public int available() throws IOException {
return 0;
}
public void close() throws IOException {}
//...
}
InputStream是个抽象类,read()方法未实现,其作用是从输入流中读取一个字节的数据,读多个字节的方法read(byte[] b)与read(byte[] b, int off, int len)都是通过read()一个字节一个字节读出的。
FileInputStream ByteArrayInputStream StringBufferInputStream PipedInputStream
均继承了InputStream,他们的区别仅仅是输入流的不同,有来自文件的,string的,byteArray的,管道的等,这导致它们read()获取下一个字节的方式可能有所不同,但思想结构都是一样的。
public
class StringBufferInputStream extends InputStream {
protected String buffer;
public StringBufferInputStream(String s) {
this.buffer = s;
count = s.length();
}
//仔细区分read代码与StringReader中的区别(有没有截取低八位的区别)
public synchronized int read() {
return (pos < count) ? (buffer.charAt(pos++) & 0xFF) : -1;
}
//...
}
mermaid sequenceDiagramInputStream
这个类可以包含多个流,然后一个一个一次读取。
ObjectInputStream
待分析
FilterInputStream
来看看源码
package java.io;
public
class FilterInputStream extends InputStream {
protected volatile InputStream in;
protected FilterInputStream(InputStream in) {
this.in = in;
}
public int read() throws IOException {
return in.read();
}
public int read(byte b[], int off, int len) throws IOException {
return in.read(b, off, len);
}
public void close() throws IOException {
in.close();
}
//...
}
FilterInputStream也继承了InputStream, 它有私有变量InputStram in;
所有inputStream的方法它都通过调用私有变量对应的方法来实现(看着和代理很像啊)。
继承FilterInputStream的一个代表类就是BufferedInputStream, 这个类的好处就是通过一个字节数组来缓存读取的内容(当读的内容超过缓存的界限时,就会重新读大段的数据到内存中),这样一次可以缓存多个字节的内容,提高访问效率; 另一个代表类是PushbackInputStream, 这个类独特的作用就是将刚从六中读出的数据塞回数据流中,可以再次读取.
字符流
Reader
Readable接口就一个函数public int read(java.nio.CharBuffer cb) throws IOException;
public abstract class Reader implements Readable, Closeable {
public int read(java.nio.CharBuffer target) throws IOException {
int len = target.remaining();
char[] cbuf = new char[len];
int n = read(cbuf, 0, len);
if (n > 0)
target.put(cbuf, 0, n);
return n;
}
public int read(char cbuf[]) throws IOException {
return read(cbuf, 0, cbuf.length);
}
abstract public int read(char cbuf[], int off, int len) throws IOException;
//....
abstract public void close() throws IOException;
}
Reader和InputStream文件结构是类似的。不同之处再出InputStream一次读一个字节,而Reader一次读取一个字符(2个字节的内容).
StringReader PipedReader CharArrayReader
都继承了Reader,只不过流的来源不同。读取字符的方式不同
public class CharArrayReader extends Reader {
protected char buf[];
public CharArrayReader(char buf[]) {
this.buf = buf;
this.pos = 0;
this.count = buf.length;
}
public int read() throws IOException {
synchronized (lock) {
ensureOpen(); //若buf为空报错
if (pos >= count)
return -1;
else
return buf[pos++];
}
}
//...
}
public class StringReader extends Reader {
private String str;
private int length;
public StringReader(String s) {
this.str = s;
this.length = s.length();
}
public int read() throws IOException {
synchronized (lock) {
ensureOpen();
if (next >= length)
return -1;
return str.charAt(next++);
}
}
//...
}
InputStreamReader(字节流转换为字符流)
是Reader的子类, 指定编码方式(不指定使用默认值),将字节流转换为字符流。
public class InputStreamReader extends Reader {
private final StreamDecoder sd;
public InputStreamReader(InputStream in) {
super(in);
try {
sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
} catch (UnsupportedEncodingException e) {
// The default encoding should always be available
throw new Error(e);
}
}
public InputStreamReader(InputStream in, String charsetName)
throws UnsupportedEncodingException
{
super(in);
if (charsetName == null)
throw new NullPointerException("charsetName");
sd = StreamDecoder.forInputStreamReader(in, this, charsetName);
}
public int read() throws IOException {
return sd.read();
}
public int read(char cbuf[], int offset, int length) throws IOException {
return sd.read(cbuf, offset, length);
}
public void close() throws IOException {
sd.close();
}
}
read方式是由类StreamDecoder完成的.它从InputStream中缓冲byte到内存中,并依据编码方式做解析,返回对应的字符
StreamDecoder流参考文档
FileReader
继承了InputStreamReader类
public class FileReader extends InputStreamReader {
public FileReader(String fileName) throws FileNotFoundException {
super(new FileInputStream(fileName));
}
public FileReader(File file) throws FileNotFoundException {
super(new FileInputStream(file));
}
public FileReader(FileDescriptor fd) {
super(new FileInputStream(fd));
}
}
就是将指定文件的FileInputStream流丢给InputStreamReader去完成任务.
输出
字节流
outputStream
字符流
Writer
OutputStreamWriter
是Writer的子类。将输出的字符流变成字节流