Skip to content

Instantly share code, notes, and snippets.

@wutingjia
Last active January 1, 2019 12:10
Show Gist options
  • Save wutingjia/a2a7ce68c2c96ba7feec1e241eabbdbb to your computer and use it in GitHub Desktop.
Save wutingjia/a2a7ce68c2c96ba7feec1e241eabbdbb to your computer and use it in GitHub Desktop.
Java IO流总结
最基本的输入流为InputStream 表示从不同数据源输入的类。因此根据不同的数据源就有不同的子类。
类 对应数据源 构造器参数
1)ByteArrayInputStream 字节数组 缓冲区,字节从内存缓冲区中取出
2)StringBufferInputStream String对象 字符串,底层使用StringBUffer
3)FileInputStream 文件 字符串,表示文件名(路径)
4)PipedInputStream 管道概念 PipedOutputStream
5)SequenceInputStream 多个InputStream 两个InputStream或一个InputStream的容器Enumeration
6)FilterInputStream 抽象类,装饰器的接口 以上其他InputStream
最基本的输出流为OutputStream 表示不同数据源输出的目标。因此根据不同的目标就有不同的子类。
类 对应数据源 构造器参数
1)ByteArrayOutputStream 字节数组 内存缓冲区初始化尺寸,用于指定数据的目的地
2)FileOutputStream 文件 字符串,表示文件名(路径)
3)PipedOutputStream 管道概念 PipedInputStream,指定用于多线程的数据的目的地
4)FilterOutputStream 抽象类,装饰器的接口 以上其他OutputStream
在有了指定了数据源的输入流之后,为了获得更加有的的属性和方法,使用上面所述的抽象类FilterInputStream对其进行“装饰”。
抽象类FilterIntputStream有以下几个实现:
类 功能 构造器参数
1)DataInputStream 与DataOutputStream搭配使用,用来数据移植 InputStream
2)BufferedInputStream 代表使用缓冲区(默认情况都会使用) InputStream
3)LineNumberInputStream 跟踪输入流中的行号 InputStream
4)PushbackInputStream 作为编译器的扫描器 InputStream
同样,在有了指定了数据源的输出流之后,为了获得更加有的的属性和方法,使用上面所述的抽象类FilterOutputStream对其进行“装饰”。
抽象类FilterOutputStream有以下几个实现:
类 功能 构造器参数
1)DataOutputStream 与DataInputStream搭配使用,用来数据移植 OutputStream
2)PrintStream 用于产生格式化输出,底层DataOutputStream OutputStream,boolean(是否在每次换行时清空缓冲区)
处理数据储存,PrintStream处理显示
3)BufferedInputStream 代表使用缓冲区(默认情况都会使用) OutputStream 还可以指定缓冲区的大小
可以调用flush()清空缓存
以上的都是最早面向字节的IO流。之后为了支持16位的Unicode与面向字符的IO功能,提供了Reader与Writer两个类。而为了与之前的面向字节的InputStream、OutputStream相互兼容,使用了适配器模式。现在最明智的做法使尽量尝试使用面向字符的Reader和Writer,只有当无法编译时,才转而回去使用面向字节的流。
字节 字符
1)InputStream Reader (适配器:InputStreamReader)
2)OutputStream Writer (适配器:OutputStreamWriter)
3)FileInputStream FileReader
4)FileOutputStream FileWriter
5)StringBufferInputStream(弃用) StringReader
6)(无对应类) StringWriter
7)ByteArrayInputStream CharArrayReader
8)ByteArrayOutputStream CharArrayWriter
9)PipedInputStream PipedReader
10)PipedOutputStream PipedWriter
与面向字节的一样,为了获得更好的行为,在确定了数据源之后对其进行“装饰”,而类结构与面向字节的有所不同。例如尽管BufferedOutputStream是FilterOutputStream的子类,但是BufferedWriter并不是FilterWriter的子类。
字节 字符
1)FilterInputStream FilterReader
2)FilterOutputStream FilterWriter(抽象类,没有子类)
3)BufferedInputStream BufferedReader (也有readLine())
4)BufferedOutputStream BufferedWriter
5)DataInputStream 只有需要readLine()方法时使用BufferedReader,其余时候就用DataInputStream
6)PrintStream PrintWriter
7)LineNumberInputStream(已弃用) LineNumberReader
8)StreamTokenizer StreamTokenizer
9)PushbackInputStream PushbackReader
还有一些类没有发生变化:
1)DataOutputStream 还是搭配DataInputStream,使用面向字节的继承结构。
2)File
3)RandomAccessFile
4)SequenceInputSream
因此一般来说,在选定使用字节还是字符层次以后,第一层选择数据源,第二层进行“装饰” 。这样就可以获得一个可以使用的IO流对象了。
在JDK1.4引入了NIO(new I/O) 目的是提高速度。
唯一与通道交互的是 ByteBuffer 它通过告知分配多少储存空间来创建一个ByteBuffer对象。他只能读取原始的字节以及基本类型,对象则不行,即使是String也不行。
有三个类被修改了,可以用来产生FileChannel:
FileInputStream、FileOutputStream、以及RandomAccessFile。注意这些是面向字节的流,面向字符的则不行。但Channels类中提供了方法,反过来产生Reader与Writer
//读文件
FileChannel fc=new FileInputStream("test.txt").getChannel();
ByteBUffer buff=ByteBuffer.allocate(1024);//分配缓冲区大小
fc.read(buff);
buff.flip();//继承自Buffer的方法把Buffer的当前位置更改为Buffer缓冲区的第一个位置,并且设置了最多只能读出之前写入的数据长度(而不是整个缓存的容量大小)
while (buffer.hasRemaining()) {
System.out.print((char)buffer.get());
}
//写文件
fc = new FileOutputStream("data.txt").getChannel();
fc.write(ByteBuffer.wrap("Some text".getBytes()));
fc.close();
// 随机读写文件(末尾添加)
fc = new RandomAccessFile("data.txt", "rw").getChannel();
System.out.println("此通道的文件位置:" + fc.position());
fc.position(fc.size());
fc.write(ByteBuffer.wrap("Some more".getBytes()));
fc.close();
while(in.read(buffer)!=-1){
buffer.flip();//准备写
out.write(buffer);
buffer.clear()//清空缓存区准备下子读入
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment