Java中的新IO流

包含在包java.nio包中。新IO将文件映射到内存中,因此读写文件速度快了不少。

支持以下特性:

内存映射文件、文件锁定、字符集编码和解码、非阻塞I/O

建立内存映射非常简单:

首先,为文件获取通道(channel)。通过FileInputStream、FileOutputStream、RandomAccessFile中的getChannel方法获取。

FileInputStream in=new FileInputStream(FilePath);

FileChannel channel=in.getChannel();

然后,调用FileChannel的map方法可以获取一个MappedByteBuffer,map的方式有三种:

FileChannel.MapMode.READ_ONLY,缓冲区只读,写入操作引发ReadOnlyBufferException异常。

FileChannel.MapMode.READ_WRITE,缓冲区可读写,这些改变会及时写回文件中。注意,如果其他程序同时映射了相同的文件,它不会立刻察觉到文件变化。多个程序同时对同一文件进行映射,其行为取决于操作系统。有可能无法互斥的操作文件,而导致同步问题,即使你锁定了文件(操作系统可能不支持锁定文件)。

FileChannel.MapMode.PRIVATE,缓冲区可读写,但任何改变只与缓冲区有关,而不会写入文件,这比较适合需要对文件安全写入的情况。

注意,map方法只是一个映射,并不是把所有内容全部读到内存中,所以,即使很大的文件,map方法也会很快返回。

最后,一旦获取了缓冲区,可以使用ByteBuffer类和Buffer超类读写数据。

缓冲区支持顺序和随机访问。

顺序访问全部字节:

while(buffer.hasRemaining())

{

byte b=buffer.get();

...

}

随机访问:

for(int i=0;i

{

byte b=buffer.get(i);

...

}

读取字节数组:

get(byte[] bytes)

get(byte[],int offset,int length)

读取基本类型数值的方法:

getInt

getLong

getShort

getChar

getFloat

getDouble

注意,Java二进制数据使用高字节在前面的顺序,如果需要处理包含低字节在前面的二进制数据文件,可以调用:

buffer.order(ByteOrder.LITTLE_ENDIAN);

要获取缓冲区当前使用的字节顺序,可调用:

ByteOrder b=buffer.order()

将基本类型数据写入缓冲区:

putInt

putLong

putShort

putChar

putFloat

putDouble

以上是一种操作文件的方法,还有一种不用MappedByteBuffer的方法,我们用普通的Buffer来实现对文件的操作:

FileInputStream fin = new FileInputStream("read.txt");

FileChannel fc = fin.getChannel(); // 获取通道

ByteBuffer buffer = ByteBuffer.allocate(1024);// 创建缓冲区

fc.read(buffer);// 将数据从通道读到缓冲区中

System.out.println((char) buffer.get(2));

// System.out.println((char) buffer.get());//直接读 会输出乱码

buffer.flip();// 将limit设置为有效值

FileOutputStream fout = new FileOutputStream("write.txt");

FileChannel fcout = fout.getChannel();

fcout.write(buffer);

关于缓冲区的使用方法:

除了上面的get和put方法外,Buffer有自己独特灵活的读写方法,所以需要知道这些方法的确切用途。

属性:

capacity属性:缓冲区容量

limit属性:当前有效容量(小于或等于limit的位置的数据是有效的)

position属性:当前读写位置

方法:

flip():刷新limit属性(当添加删除元素的时候,limit是不会自动刷新的,所以每次对缓冲区元素个数进行操作的时候,需要调用flip()),重置position为0。

clear():逻辑上清空缓冲区。将position和limit都设置为0。之所以是逻辑上清空,是因为,相应位置上的数据没有被擦写,只是limit成为0了。

hasRemaining():如果还有没读完的数据,返回true(常用于循环遍历读取的时候判断结尾)。

公式:0<=position<=limit<=capacity

以下小例子可以证明这些结论:

import java.nio.*;

public class NewIOBufferExercise1 {

/**

* @param args

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

CharBuffer buff=CharBuffer.allocate(8);

System.out.println("capacity:"+buff.capacity());

System.out.println("limit:"+buff.limit());

System.out.println("position:"+buff.position());

buff.put('a');

buff.put('b');

buff.put('c');

System.out.println("加入三个元素后,position="+buff.position()+",limit="+buff.limit());

buff.flip();

System.out.println("执行flip方法后,position="+buff.position()+",limit="+buff.limit());

System.out.println("第一个元素:"+buff.get());

System.out.println("取出第一个元素后,position="+buff.position());

buff.clear();

System.out.println("执行clear方法后,position="+buff.position()+",limit="+buff.limit());

System.out.println("执行clear方法后,缓冲区没有被消除,用get取得第三个元素是="+buff.get(2));

System.out.println("执行绝对读取get后,position="+buff.position());

}

}

执行结果是:

capacity:8

limit:8

position:0

加入三个元素后,position=3,limit=8

执行flip方法后,position=0,limit=3

第一个元素:a

取出第一个元素后,position=1

执行clear方法后,position=0,limit=8

执行clear方法后,缓冲区没有被消除,用get取得第二个元素是=c

执行绝对读取get后,position=0

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值