InputStream,OutputStream源码理解
1.理解字节流和字符流
按流的形式分:
字节流和字符流。
字节流的两个顶峰:InputStream 和OutputStream
字符流的两个顶峰:Reader Writer
字节流可以处理二进制数据的。
字符流不能处理二进制数据,字符流的底层是字节流实现的。
流是一种资源,打开后记得关闭。
流的来源和去向是 文件、网络和内存
本文说明InputStream,FileInputStream,OutputStream,FileOutputStream 四个对象
2.InputStream (FileInputStream)
read
有三个read方法,一个抽象的方法,其他两个不是。
InputStream input =new FileInputStream(f); input.read() ;//返回int型
FileInputStream 对象实现了native的read方法,应该是适用于文件读写的规则。
read返回一个int型,是文档中的字符所代表的ascii码。
read这个方法很清晰,就是将每一个字符读出,如果为-1 结束,不是则强转成byte,读满后结束,还有那个read方法里每次读取的位置都应该在内部记录了。
public int read(byte b[]) throws IOException { return read(b, 0, b.length); } 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(); //如果结束了,直接返回-1 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; }
上面的read()是抽象方法,在不同的类中会按照不同的协议(网络或者文件)读取。
skip()
skip就是执行n词read后,跳到想去的地方,还不如手动执行read一个长度。在FileInputStream里面,我怀疑跳跃应该不是这种实现。
//跳过多少字节,返回跳过的实际字节数 public long skip(long n) throws IOException { //一个临时变量。 long remaining = n; int nr; if (skipBuffer == null) skipBuffer = new byte[SKIP_BUFFER_SIZE]; byte[] localSkipBuffer = skipBuffer; if (n <= 0) { return 0; } //这是主要的方法,通过执行n词read实现跳过。 while (remaining > 0) { nr = read(localSkipBuffer, 0, (int) Math.min(SKIP_BUFFER_SIZE, remaining)); if (nr < 0) { break; } remaining -= nr; } //返回实际跳转的字节。 return n - remaining; }
mark,reset,close
mark标记一个位置,reset还原到这个位置,close 关闭流。
三个方法内部都没有内容。
在FileInputStream里面mark,reset都没有用到,close做了覆写。
3.OutputStream(FileOutputStream)
写数据,简单的例子
public static void main(String args[]) throws IOException { File f = new File("src/wan1.txt"); OutputStream out =new FileOutputStream(f); out.write("天天向上".getBytes()); out.write(78);//O out.flush(); out.close(); }
构造函数
在FileOutputStream的构造函数中也仅仅是判断了一些权限,然后几个native方法。
在构造函数中还可以在后面加入一个参数,boolean append 用来判断是从文件开始写还是从文件末尾写。默认false,从开始写。
write()
和read一样,覆写一个无参的write方法,然后简单的逻辑判断。
flush()
OutputStream里面没代码,在FileOutputStream里面没有覆写,看来在文件写上面没有起到作用。
close()
OutputStream里面没代码,在FileOutputStream里面覆写了native方法。
这次源码又都是native方法。
上一篇: mysql查询将两列数值相加问题
下一篇: PHP类定义与实例化
推荐阅读
-
spring5 源码深度解析----- 事务的回滚和提交(100%理解事务)
-
Spring MVC源码(三) ----- @RequestBody和@ResponseBody原理解析
-
java中Object源码理解
-
理解merge和pushStack可以更好的了解jQuery源码
-
从源码角度理解Android线程
-
初学者从源码理解MySQL死锁问题
-
持久层Mybatis3底层源码分析,原理解析
-
.NET Core 3.0之深入源码理解Configuration(二)
-
.NET Core 3.0之深入源码理解Configuration(三)
-
Java 并发系列(一) ThreadPoolExecutor源码解析及理解