Java 之NIO(二) - Channel

来源:互联网 发布:linux 如何设置ntp 编辑:程序博客网 时间:2024/05/16 07:18

简介:

本节主要内容包括通过Channel(通道)对文件进行读写操作,通道类似于之前的输入/输出流,程序不会直接操作通道,通常都是将数据读入到缓冲区中,然后再从缓冲区中读写数据,与传统的输入输出流相比,通道是双向操作的,既可以完成输入,也可以完成输出。

另外,本节还会讲解一下内存映射,内存映射指的是将文件映射到内存中,这样就可以使用系统调用函数进行内存读写,采用这样的方式读取文件是速度最快的。

下面通过代码示例,来描述FileChannel进行文件读写以及FileChannel提供的map方法进行内存映射的使用步骤,为了简化文字篇幅,以下代码我会做详细的注释,相信大家会一目了然。

文件写操作:

package com.ray.nio.demo;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/**
 * FileChannel是Channel的子类,可以进行文件的读写操作,使用FileChannel可以通过FileInputStream 和 FileOutputStream获得。
 * 本示例演示了使用FileChannel写入操作,首先将内容放入缓冲区中,然后使用输出通道将数据输出到文本文件中。
 * @author xuleilei
 *
 */
public class ChannelWrite {

public static void main(String[] args) {
String outputMsg = "这是一段测试代码!abc123!@#";

FileOutputStream fos = null;//文件输出流
FileChannel fileChannel = null;//读写文件的通道
try {
fos = new FileOutputStream(new File("test.txt"));
fileChannel = fos.getChannel();//通过文件输出流获取输出通道
// 开辟字节缓冲区,并指定缓冲区大小
ByteBuffer buf = ByteBuffer.allocate(outputMsg.getBytes().length);
buf.put(outputMsg.getBytes());//将数据存放在字节缓冲区中
buf.flip(); //重设缓冲区

// 通过写通道,将缓冲区中的数据输出到目标文件中
fileChannel.write(buf);

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileChannel.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

文件读写操作:

package com.ray.nio.demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/**
 * FileChannel进行文件边读边写操作。
 * @author xuleilei
 *
 */
public class ChannelReadWrite {

public static void main(String[] args) {

FileInputStream fis = null;//文件输入流
FileOutputStream fos = null;//文件输出流
FileChannel fin = null;//文件输入通道
FileChannel fout = null;//文件输出通道
try {
fis = new FileInputStream(new File("in.txt"));
fos = new FileOutputStream(new File("out.txt"));
// 注意,通过输入,输出文件流获取对应的通道
fin = fis.getChannel();
fout = fos.getChannel();

ByteBuffer buf = ByteBuffer.allocate((int) new File("in.txt").length());

while(fin.read(buf) != -1){
buf.flip();
fout.write(buf);
buf.clear();
}


} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fin.close();
fout.close();
fis.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

内存映射:

在使用FileChannel的map方法进行映射时,FileChannel$MapMode类提供了三种映射模式:

/*** Mode for a read-only mapping.*/
public static final MapMode READ_ONLY = new MapMode("READ_ONLY");

/*** Mode for a read/write mapping. */
public static final MapMode READ_WRITE  = new MapMode("READ_WRITE");

/*** Mode for a private (copy-on-write) mapping. */
public static final MapMode PRIVATE  = new MapMode("PRIVATE");

package com.ray.nio.demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
/**
 * 内存映射
 * @author xuleilei
 *
 */
public class ChannelMemMap {
public static void main(String[] args) {
FileInputStream fis = null;
FileChannel fc = null;
try {
File file = new File("in.txt");
fis = new FileInputStream(file);
fc = fis.getChannel();
// 通过FileChannel将文件映射到内存中,并设置映射模式为只读
MappedByteBuffer mbb = fc.map(MapMode.READ_ONLY, 0, file.length());
byte[] data = new byte[(int) file.length()];

for(int i=0;mbb.hasRemaining();i++){
data[i] = mbb.get();
}
System.out.println(new String(data));


} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fc.close();
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}


0 0
原创粉丝点击