标签:
一:输入流,
字节流(二进制字节)
1. InputStream 类,抽象类代表一输入流
?
2. 具体的流类:
AudioInputStream, ByteArrayInputStream, FileInputStream, FilterInputStream, ObjectInputStream, PipedInputStream, SequenceInputStream, StringBufferInputStream
InputStream 类的子类 代表不同来源的流。例如: ByteArrayInputStream流的来源是:字节数组。FileInputStream流的来源是文件。
?
3. 包装的功能流类
BufferedInputStream, CheckedInputStream, CipherInputStream, DataInputStream, DeflaterInputStream, DigestInputStream, InflaterInputStream, LineNumberInputStream, ProgressMonitorInputStream, PushbackInputStream
这些类都是 java.io.FilterInputStream 类的子类,他们的作用是提供一些读取流的特殊功能,例如按行来读取流 LineNumberInputStream 流。使用缓冲区的流泪:BufferedInputStream。所以这些类的构造方法都是 InputStream 类的子类。也就是2中的具体的流类。A FilterInputStream contains some other input stream, which it uses as its basic source of data, possibly transforming the data along the way or providing additional functionality.
?
字符流
1. java.io.Reader 所有字符流的抽象基类。
2. 具体的字符流类:BufferedReader, CharArrayReader, FilterReader, InputStreamReader, PipedReader, StringReader
每一种流类代表一种字符流的来源。
3. 同样地 FilterReader 类,代表了字符流的功能包装流。
?
类似的,有输出流:
//////////
?
从本质上看,字符流其实就是字节流,字符流也是一些二进制数据,只不过这些二进制数据可以通过,指定 字符集(charset), 将其映射到可以显示的字符上,所以我们称之为字符流。所以 jdk 提供了一种将字节流转换成字符流的方法,就是 InputStreamReader 类,通过给这个类提供一个InputStream类和字符集名称,可以将该字节流转换成字符流。之后就可以使用字符流的功能来,操纵原来的字节流。
?
?
字符集:又是一个新话题:
?
?
java.nio包中的类:
这个包中的类新的IO架构,其思路和之前的基于流的I/O完全不同。基于流的I/O其基本假设是:具备I/O操作的实体(例如:文件,socket(网络), 内存区域(字符串,字节数组)),其输入和输出都是按照其数据在其中的顺序,来读写。而且这种流式操作,读取字节数据是常常是不可逆的,按照其读取顺序,直到文件末尾。所以这种流失的读写是一种阻塞式的I/O模型,并且不是线程安全的:例如:FileInputStream类:
private native void open(String name) throws FileNotFoundException;
public native int read() throws IOException;
private native int readBytes(byte b[], int off, int len) throws IOException;
这几个核心的方法都是 native 的。所以对于流失I/O来说,每次的数据读写,都要直接对目标文件(或内存区域)进行读写。
而对于 java.nio.channels 中的 FileChannel类,其每次操作的都是ByteBuffer:例如:读的方法:
abstract int read(ByteBuffer dst)
long read(ByteBuffer[] dsts)
abstract long read(ByteBuffer[] dsts, int offset, int length)
abstract int read(ByteBuffer dst, long position)
写的方法:
abstract int write(ByteBuffer src)
long write(ByteBuffer[] srcs)
abstract long write(ByteBuffer[] srcs, int offset, int length)
abstract int write(ByteBuffer src, long position)
那么什么是缓冲区呢,其实就是一块内存区域,这块区域中定义了一些管理这块内存区域的方法:limit , position, mark等等。同时他也是数据的容器,用来暂时存放数据。其实nio中的数据操作更多的就是在这个data buffer中,Channel中提供的 read 和 write方法用来生成和消费Data Buffer的,有了read生成出来的Buffer,我们就可以在这个Buffer进行读写操作了。所以对于Buffer类的具体子类,都提供了类似与:get, put方法,用来操纵Buffer中的data.对Buffer中的data进行一系列的业务处理之后,我们就可以使用Channel的write方法一次性的将这个Buffer写到目标中去。所以这种操作机制大大降低了,实际的I/O次数。提高了I/O效率。
4M的文件:计算 CRC32
Input Stream:????fe935a6f????13342 milliseconds
Buffered Input Stream:????fe935a6f????111 milliseconds
Random Access File:????fe935a6f????19526 milliseconds
Mapped File:????fe935a6f????80 milliseconds
8M的文件:
Input Stream:????8b40d037????26994 milliseconds
Buffered Input Stream:????8b40d037????145 milliseconds
Random Access File:????8b40d037????38734 milliseconds
Mapped File:????8b40d037????125 milliseconds
13M的文件:
Input Stream:????13693a09????16884 milliseconds
Buffered Input Stream:????13693a09????217 milliseconds
Random Access File:????13693a09????32616 milliseconds
Mapped File:????13693a09????186 milliseconds
26M的文件:
Input Stream:????ee040d90????33103 milliseconds
Buffered Input Stream:????ee040d90????447 milliseconds
Random Access File:????ee040d90????62611 milliseconds
Mapped File:????ee040d90????360 milliseconds
500M的文件:
Buffered Input Stream:????8e60e18e????19057 milliseconds
Mapped File:????8e60e18e????17359 milliseconds
由此可见使用 Buffered Input Stream 和 Mapped File在性能是很好的。
?
2. java.nio.Buffer类的层次结构:
Buffer类定义了缓冲区的状态和状态操作字段:
状态字段:capacity, limt, position, mark.
状态读写方法:
capacity()
position()
position(int)
limit()
limit(int)
mark()
reset()
clear()
flip()
rewind()
remaining()
hasRemaining()
都是对状态位进行操作,其实也就是缓冲区所拥有的具体操作:
Buffer类的具体子类:例如:ByteBuffer类,这个类也是一个抽象类:
他定义一些系列关于字节(Byte)读写的方法:put, putXXX, get, getXXX,这些个基本操作也都是抽象的,因为这个此时的缓冲区,还没有指明缓冲区分配的介质,ByteBuffer的子类,java.nio.HeapByteBuffer 和 java.nio.DirectByteBuffer 最终代表缓冲区存储介质的抽象,HeapByteBuffer在JVM堆上分配缓冲区内存,DirectByteBuffer在系统底层的内存。这三层抽象各有不同:Buffer抽象了缓冲区具有的基本操作,ByteBuffer抽象了缓冲区的字节读写操作,而 HeapByteBuffer 则抽象了在JVM堆上分配的字节缓冲区。其他类型的缓冲区实现类似。
3. Channel
java.io.FileInputStream类的getChannel,第三个参数表明,这个channel是不可写的。第二个参数表明这个通道是可读的。
public FileChannel java.io.FileInputStream.getChannel() {
synchronized (this) {
if (channel == null) {
channel = FileChannelImpl.open(fd, true, false, this);
fd.incrementAndGetUseCount();
}
return channel;
}
}
java.io.FileOutputStream.getChannel的getChannel方法:表明这个channel是不可读(不能调用read系列方法。),只可以写的。
public FileChannel java.io.FileOutputStream.getChannel() {
synchronized (this) {
if (channel == null) {
channel = FileChannelImpl.open(fd, false, true, append, this);
fd.incrementAndGetUseCount();
}
return channel;
}
}
在文档中也表明:这个方法是在java1.4加入的。也就是在 java.nio加入的时候,添加的这两个方法。
java.io.RandomAccessFile类的 getChannel ,这个流是可读的,同时是否可以写取决与rw参数,也就是创建RandomAccessFile类的实例是的可读可写标志位。
public final FileChannel getChannel() {
synchronized (this) {
if (channel == null) {
channel = FileChannelImpl.open(fd, true, rw, this);
fd.incrementAndGetUseCount();
}
return channel;
????}
}
标签:
原文地址:http://www.cnblogs.com/a-ray-of-sunshine/p/4658729.html