java编程思想笔记(十三) I/O(二)
1.新I/O
JDK 1.4的java.nio.*包引入了新I/O类库,目的是为了提高速度,速度的来源是使用的结构更接近与操作系统的执行I/O 的方式:通道和缓冲器,通道指FileChannel,缓冲器指ByteBuffer,旧I/O类库有三个类改变了,可以产生FileChannel,这三个类是FileInputStream,FileOutputStram和RandomAccessFile,
下面代码用以产生这三种流可写,可读写,可读的通道
public class GetChannel { private static final int BSIZE = 1024; @SuppressWarnings("resource") public static void main(String[] args) throws Exception { FileChannel fc = new FileOutputStream("data.txt").getChannel(); fc.write(ByteBuffer.wrap("Some text".getBytes())); fc.close(); fc = new RandomAccessFile("data.txt", "rw").getChannel(); fc.position(fc.size()); // Move to the end fc.write(ByteBuffer.wrap("Some more".getBytes())); fc.close(); fc = new FileInputStream("data.txt").getChannel(); ByteBuffer buff = ByteBuffer.allocate(BSIZE); fc.read(buff); buff.flip(); while (buff.hasRemaining()) System.out.print((char) buff.get()); } }
输出结果:
Some text Some more
通道可以用isOpen()看是否是通道打开状态,一般是线程安全的
字节缓冲区可以存放原始字节,也可以存放java的8中基本类型数据,但是不能存放引用类型数据,String也是不能存放的。正是由于这种底层的存放类型似的字节缓冲区可以更加高效和绝大部分操作系统的I/O进行映射。由allocate(n)获得缓冲器,其中n是你所分配的空间.
字节缓冲区的常用操作:
(1).读写单个字节的绝对和相对get和put方法:
a. 绝对方法:
get(int index):读取指定索引处的字节。
put(int index, byte b):将字节写入指定索引处。
b.相对方法:
get():读取此缓冲区当前位置的字节,然后该位置递增。
put(byte b):将字节写入此缓冲区的当前位置,然后该位置递增。
(2).相对批量get方法:
ByteBuffer get(byte[] dst):将此缓冲区的字节传输到给定的目标数组中。
(3).相对批量put方法:
ByteBuffer put(byte[] src):将给定的源byte数组的所有内容传输到此缓冲区中。
(4).读写其他基本类型值:
getChar(), putChar(char value), getChare(int index), putChar(int index, char value).
getInt(), putInt(int value), getInt(int index), putInt(int index, int value)等等读写基本类型值得相对和绝对方法。
注意:基本类型值得相对和绝对读写方法,根据java基本类型数据底层字节数进行缓冲区移动。
(5).创建视图缓冲区:
为了访问同类二进制数据,允许将字节缓冲区视为包含它们基本类型值的缓冲区,视图缓冲区只是其内容受该字节缓冲区支持的另一种缓冲区。字节缓冲区和视图缓冲区内容更改是相互可见的。这两种缓冲区的位置、限制和标记值都是独立的。创建方法如下:
asCharBuffer(), asDoubleBuffer(), asFloatBuffer(), asIntBuffer(), asLongBuffer(), asReadOnlyBuffer(), asShortBuffer()。
与具体类型的get和put方法系列相比,视图缓冲区优势如下:
a视图缓冲区不是根据字节进行索引,而是根据其特定类型的值得大小进行索引。
b.视图缓冲区提供了相对批量get和put方法,这些方法可以在缓冲区和数组或相同类型的其他缓冲区直接传输连续序列的值。
c.视图缓冲区可能更搞效,因为当且仅当其支持的字节缓冲区为直接缓冲区时它才是直接缓冲区。
2.文件复制:
文件通道和字节缓冲区不但可以实现数据从文件读入和读出,还可以实现文件的复制,例子如下:
import java.nio.*; import java.nio.channels/*; import java.io.* public class FileCopy{ //字节缓冲区大小 private static final int BSIZE = 1024; public static void main(String[] args) throws Exception{ //获取文件输入通道 FileChannel in = new FileInputStream(“FileCopy.java”).getChannel(); //获取文件输出通道 FileChannel out = new FileOutputStream(“FileOut.txt”).getChannel(); ByteBuffer buffer = ByteBuffer.allocate(BSIZE); While(in.read(buffer) != -1){ //重置缓冲区,准备写出 buffer.flip(); //将字节缓冲区内容写出到文件输出通道 out.write(buffer); //清除字节缓冲区 buffer.clear(); } } }
3.文件通道传输:
文件通道的transferFrom(ReadableByteChannel src, long position, long count)方法将字节从给定的可读字节通道传输到此通道的文件中,transferTo(long position, long count, WritableByteChannel target)方法将此通道的文件传输到给定的可写字节通道。例子如下:
import java.nio.channels.*; import java.io.* public class ChannelTransfer{ public static void main(String[] args) throws Exception{ FileChannel in = new FileInputStream(“ChannelTransfer.java”).getChannel(); FileChannel out = new FileOutputStream(“out.txt”).getChannel(); //将输入文件通道传输到输出文件通道 in.transferTo(0, in.size(); out); //从输入文件通道传输到输出文件通道 out.transferFrom(in, 0, in.size()); } }