FileChannel的使用
Java NIO中的FileChannel是一个连接到文件的通道。可以通过文件通道读写文件。
FileChannel无法设置为非阻塞模式,它总是运行在阻塞模式下。
一.打开FileChannel
在使用FileChannel之前,必须先打开它。但是,我们无法直接打开一个FileChannel,需要通过使用一个InputStream、OutputStream或RandomAccessFile来获取一个FileChannel实例
下面是通过RandomAccessFile打开FileChannel的示例:
RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");
FileChannel inChannel = aFile.getChannel();
RandomAccessFile类的构造方法如下所示:
RandomAccessFile(File file , String mode)
//创建随机存储文件流,文件属性由参数File对象指定
RandomAccessFile(String name , String mode)
//创建随机存储文件流,文件名由参数name指定
[注意]
这两个构造方法均涉及到一个String类型的参数mode,它决定随机存储文件流的操作模式,其中mode值及对应的含义如下:
- “r”:以只读的方式打开,调用该对象的任何write(写)方法都会导致IOException异常
- “rw”:以读、写方式打开,支持文件的读取或写入。若文件不存在,则创建之。
- “rws”:以读、写方式打开,与“rw”不同的是,还要对文件内容的每次更新都同步更新到潜在的存储设备中去。这里的“s”表示synchronous(同步)的意思
- “rwd”:以读、写方式打开,与“rw”不同的是,还要对文件内容的每次更新都同步更新到潜在的存储设备中去。使用“rwd”模式仅要求将文件的内容更新到存储设备中,而使用“rws”模式除了更新文件的内容,还要更新文件的元数据(metadata),因此至少要求1次低级别的I/O操作
二.从FileChannel读取数据
调用多个read()方法之一从FileChannel中读取数据。如:
ByteBuffer buf = ByteBuffer.allocate(48); int bytesRead = inChannel.read(buf);
首先,分配一个Buffer。从FileChannel中读取的数据将被读到Buffer中。
然后,调用
FileChannel.read()方法
。该方法将数据从FileChannel读取到Buffer中。read()方法返回的int值表示了有多少字节被读到了Buffer中。如果返回-1,表示到了文件末尾。
三.向FileChannel写数据
使用FileChannel.write()方法向FileChannel写数据,该方法的参数是一个Buffer。如:
String newData = "New String to write to file..." + System.currentTimeMillis();
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());
buf.flip();
while(buf.hasRemaining()) {
channel.write(buf);
}
[注意]:
注意FileChannel.write()是在while循环中调用的。因为无法保证write()方法一次能向FileChannel写入多少字节,因此需要重复调用write()方法,直到Buffer中已经没有尚未写入通道的字节。
四.关闭FileChannel
用完FileChannel后必须将其关闭。如:
channel.close();
例子:
例一:
package cn.cc.Nio;
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;
/**
* @author CC
* 非阻塞IO
*/
public class NioDemo2 {
public static void main(String[] args) {
NioDemo2 n = new NioDemo2();
n.writeFile();
n.readFile();
}
public void readFile() {
//NIO读取文件
FileInputStream fis = null;
FileChannel fc = null;
try {
fis = new FileInputStream("F:\\out.txt");
fc = fis.getChannel();
//创建缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024);
//读取内容到缓冲区
int length = fc.read(buffer);//读取到的长度
System.out.println("读取到"+length);
//从缓冲区获取数据
buffer.flip();
byte[] ary = new byte[length];
buffer.get(ary);//把缓冲区的内容获取到后,存入ary数组中
System.out.println(new String(ary));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void writeFile() {
//NIO写入文件
// 创建输出流
FileOutputStream fos = null;
FileChannel fc = null;
try {
fos = new FileOutputStream("F:\\out.txt");
// 获取通道
fc = fos.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put("wo shi cui chen".getBytes());
buffer.flip();
// 通过通道写入目标文件
fc.write(buffer);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fc != null) {
fc.close();
}
if (fos != null) {
fos.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
例二:
package cn.cc.Nio;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
public class NioDemo3 {
public static void main(String[] args) {
//创建通道
FileChannel inChannel = null;
FileChannel outChannel = null;
try {
//读取大文件
inChannel = new RandomAccessFile("F:\\c", "r").getChannel();
//写入大文件
outChannel = new RandomAccessFile("D:\\o", "rw").getChannel();
//把内存映射为缓冲区
MappedByteBuffer map = inChannel.map(MapMode.READ_WRITE, 0, inChannel.size());
//把内存缓冲区的内容写道输出管道
outChannel.write(map);
System.out.println("读取结束!");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if (outChannel!=null) {
try {
outChannel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (inChannel!=null) {
try {
inChannel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
基本步骤
总结:
- 通过通道写入文件:
代码—>写入(write)缓冲区(buffer)—>通道(Channel)—>目标文件(File)
- 通过通道读取文件:
目标文件(File)—>通道(Channel)读取到(read)—>缓冲区(buffer)—>代码中