java编程思想读书笔记 第十八章 java I/O系统(第四篇 新I/O)

新的I/O

JDK1.4的java.nio.*包中引入了新的javaI/O类库,其目的在于提高速度,旧的I/O包已经使用nio重新实现过,以便充分利用这种速度提高。因此,即便我们不显示的使用nio编写代码。也能从中受益。速度的提高在于所使用的结构更接近与操作系统执行的I/O方式:通道和缓冲器
ByteBuffer是唯一直接与通道交互的缓冲器,可以存储未加工字节的缓存器;java.nio.ByteBuffer是相当基础的类,通过告知分配多少存储空间来创建一个ByteBuffer对象,并且还有一个方法选择集,用于以原始的字节形式或基本数据类型输出和读取数据。没办法输出或读取对象;通过告知分配多少存储空间来创建一个ByteBuffer对象。
旧I/O类库中有三个类被修改了,用以产生FileChannel。这三个被修改的类是FileInputStream、FileOutputStream以及用于既读又写的RandomAccessFile。注意这些事字节操作流。Reader和Writer这种字符模式类不能用于产生通道,但是java.nio.Channels提供了实用方法,用以在通道中产生Reader和Writer。
下面的例子使用了上面三种类型的流,用以产生可写的、可读可写的及可读的通道。例子如下:

public class GetChannel {

    private static final int BSIZE = 1024;
    public static void main(String[] args) throws Exception{
        FileChannel fChannel = new FileOutputStream("").getChannel();
        fChannel.write(ByteBuffer.wrap("".getBytes()));
        fChannel.close();
        fChannel = new RandomAccessFile("文件名字", "rw").getChannel();
        fChannel.position(fChannel.size());
        fChannel.write(ByteBuffer.wrap("文件名字".getBytes()));
        fChannel.close();
        fChannel = new FileInputStream("文件名字").getChannel();
        ByteBuffer buffer = ByteBuffer.allocate(BSIZE);
        fChannel.read(buffer);
        buffer.flip();
        while (buffer.hasRemaining()) {
            System.out.println((char)buffer.get());
        }

    }
}

对于这里展示的任何流,getChannel()将会产生一个FileChannel。可以向它传送用于读写的ByteBuffer,并且可以锁定文件的某些区域用于独占式访问。
将字节存放于ByteBuffered的方法:
1)使用一种“put”方法直接对它们进行填充,填入一个或多个字节,或基本数据类型的值。
2)也可以使用warp()方法将已存在的字节数组“包装”到ByteBuffer中。一旦如此,就不再复制底层的数组,而是把它作为所产生的ByteBuffer的存储器。我们称之为数组支持的ByteBuffer。
对于只读访问,必须显示的使用静态的allocate()方法分配ByteBuffer。allocateDirect()是更高的速度,但是由于它依赖于平台,随着平台不同而不同,故需要谨慎使用。
一旦调用FileChaal.read(ByteBuffer)来告知FileChannal向ByteBuffer存储字节,就必须使用缓冲器上的flip();如果我们打算使用缓冲器执行进一步的read()操作,必须调用clear()来为每个read()做好准备
1)flip():反转此缓冲区,将限制设置为当前位置,然后将位置设置为0
2)rewind():返回到数据开始部分,与flip()不同,不会修改限制位置。
3)FileChannal.read():返回-1表示我们已经到达了输入的末尾。
4)flip()是准备缓存器,以便他的信息可以由write()提取。write()操作之后,信息仍在缓冲器中,接着clear()操作则对所有的内部指针重新安排,以便缓冲器在另一个read()操作期间能够做好接收数据的准备。

1. 转换数据
缓冲器容纳的是普通的字节,为了把它们转换成字符,要么在输入的时候对其进行编码,要么在将其从缓冲器输出时对它们进行编码。可以使用java.nio.Charset类实现这些功能,该类提供了把数据编码成多种不同类型的字符集的工具。

2. 获取基本类型
尽管ByteBuffer只能保存字节类型的数据,但是它具有可以从其所容纳的字节中产生出各种不同的基本类型值的方法。
向ByteBuffer插入基本类型数据的简单方法使:利用acCharBuffer()、asShortBuffer()等获得该缓冲上的视图,然后使用视图的put()方法。此方法适用于所有的基本类型,仅有一个小小的例外,即使用ShortBuffer的put()方法时,需要进行类型转换,而其他所有的视图缓冲器使用put()方法时,不需要进行类型转换。

3. 视图缓冲器
视图缓冲器可以让我们通过某个特定的基本数据类型的视窗查看其底层的ByteBuffer。ByteBuffer依然是实际存储数据的地方,“支持”着前面的视图,因此,对视图的任何修改都会映射成为对ByteBuffer中数据的修改。
一旦底层的ByteBuffer通过视图缓冲器填满了整数或其他基本类型时,就可以直接被写到通道中了。正向向从通道中读取那样容易,然后使用视图缓冲器可以把任何数据都转化成某一特定的基本类型。

4. 用缓冲器操纵数据
如果想把一个字节数组写到文件中去,那么就应该使用ByteBuffer.wrap()方法把字节数组包装起来,然后用getChannel()方法在FileOutputStream上打开一个通道,接着将来自于ByteBuffer的数据写到FileChannel中。注意:ByteBuffer是将数据移进移出通道的唯一方式,并且只能创建一个独立的基本类型缓冲器,或者使用“as”方法从ByteBuffer中获得。也就是说,我们不能把基本类型的缓冲器转换成ByteBuffer。然后,由于可以由视图缓冲器将基本类型数据移进移出ByteBuffer,所以这也不是什么真正的限制了。

你可能感兴趣的:(java编程思想读书笔记,java,读书笔记,编程,io)