Java nio(3)

Java nio(三)
一、读文件:
前面我们介绍了通过获得FileChannel来写文件,现在我们再看看读操作。
其实读操作和写操作基本是对应的。
首先与写操作类似从文件中获得流,读操作要获得输入流FileInputStream
,再从这个流中得到FileChannel对象,然后进行读操作。
文件通道的读操作有三个read()方法:
int read(ByteBuffer buf);
从文件中读取buf.remaining()[即limit-position]个字节到缓冲区buf,从缓冲区的当前位置开始存取
int read(ByteBuffer[] buffers);
从文件中读到多个缓冲区中
int read(ByteBuffer[] buffers,int offset,int length);
从文件中读到buffers[offset]--buffers[offset+length-1]缓冲区中

用个小例子描述上面的过程:
File file = new File("D:\text.txt");
FileInputStream fis = new FileInputStream(file);
FileChannel inputChannel = fis.getChannel();
ByteBuffer buf = ByteBuffer.allocate(48);
while(inChannel.read(buf) != -1){
  //....从buf中提取出数据;for example:
  System.out.println(buf.filp().asCharBuffer().toString());
  buf.clear();
}

二、文件复制:
文件通道定义了两个方法,可以进行直接的文件传输:
int transferTo(int position,long count,WritableByteChannel dst);
这个函数是把文件从position位置开始向dst通道传送count个字节。
int transferFrom(ReadableByteChannel src,long position,long count);
将count个字节从通道src传送到文件中,position是为文件开始写入的位置。
从FileInputStream中获得的通道只支持transferTo,而从FileOutputStream中获得
的通道只支持tansferFrom()方法
举个小例子来说明这个过程:
  File fromFile = new File("D:/from.txt");
  File toFile = new File("D:/to.txt");
  FileInputStream fis = new FileInputStream(fromFile);
  FileOutputStream fos = new FileOutputStream(toFile);
  FileChannel inChannel = fis.getChannel();
  FileChannel outChannel = fos.getChannel();
  int byteWritten = 0;
  long byteCount = inChannel.size();
  while(byteWritten < byteCount){
    byteWritten += inChannel.transferTo(bytesWritten,byteCount- bytesWritten,outChannel);
  }
  fis.close();
  fos.close();

也可以使用outChannel的transferFrom()方法复制数据,他们都可以一次传送所有的
数据,万一没有一次传送所有的数据,可以使用类似上面的while循环来处理。
三、随机读取文件:
FileChannel定义了两个方法用来进行随机读写操作:
int read(ByteBuffer buf,long position);
从文件的position位置开始读取字节到buf中
int write(ByteBuffer buf,long position);
把buf的数据,从文件的position开始写入到文件中
四、一个通道进行文件的读写
上面提到的从FileInputStream和FileOutputStream获得的通道只能进行读或者写操作,
如果我们想得到一个通道,同时可以进行读和写操作,那该怎么办?
从RandomAccessFile获得的通道就是这样一个通道。
File file = new File("D:\test.txt");
RandomAccessFile raf = new RandomAccessFile(file,"rw");
FileChannel ioChannel = rad.getChannel();

五、内存映像文件:
内存映像文件是这样的文件,它的内容被映像到计算机虚拟内存的一块区域,这样就可以
直接的使用和更新文件中的数据了,可以很大的提高效率。
FileChannel提供了map方法来把文件影射为内存映像文件:
MappedByteBuffer map(int mode,long position,long size);
可以把文件的从position开始的size大小的区域映射为内存映像文件,mode指出了
可访问该内存映像文件的方式:READ_ONLY,READ_WRITE,PRIVATE.
详细可以参考java API
MappedByteBuffer类还提供了三个方法:
fore();缓冲区是READ_WRITE模式下,此方法对缓冲区内容的修改强行写入文件
load()将缓冲区的内容载入内存,并返回该缓冲区的引用
isLoaded()如果缓冲区的内容在物理内存中,则返回真,否则返回假
File file = new File("D:\test.txt");
RandomAccessFile raf = new RandomAccessFile(file,"rw");
FileChannel ioChannel = rad.getChannel();
MappedByteBuffer buf = ioChannel.map(READ_WRITE.0L,ioChannel.size()).load();

后面总结有关从Socket获得到SocketChannel进行异步通讯的问题。
1 楼 fuliang 2008-03-02  
另外补充一下读写基本类型的例子:
写入基本类型:
 public static void testWritePrimitiveBuffer()throws Exception{
       int i = 10;
       long l = 10L;
       double d = 29.01;
       char ch = 'c';
       ByteBuffer buffer = ByteBuffer.allocate(100);
       buffer.putInt(i).putLong(l).putDouble(d).putChar(ch);
       FileOutputStream fos = new FileOutputStream(new File("D:/primitive.txt"));
       FileChannel outputChannel = fos.getChannel();
       buffer.flip();
       outputChannel.write(buffer);
    }

读入基本类型:
将刚写入的数据读出:
public static void testReadPrimitiveBuffer()throws Exception{
       int i;
       long l;
       double d;
       char ch;
       ByteBuffer buffer = ByteBuffer.allocate(100);
       FileInputStream fis = new FileInputStream(new File("D:/primitive.txt"));
       FileChannel inputChannel = fis.getChannel();
       inputChannel.read(buffer);
       buffer.flip();
       i = buffer.getInt();
       l = buffer.getLong();
       d = buffer.getDouble();
       ch = buffer.getChar();
       System.out.println("i=" + i + ",l=" + l + ",d=" + d + ",ch=" + ch);
    }
2 楼 bojianpc 2008-09-08  
不错哦最近项目要用 可以向你请教此类的问题么 我的QQ1067302 希望能得到你的恢复