21.NIO中FileChannel的使用

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)—>代码中

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值