文件通道

 目的:Channel用于在字节缓冲区和位于通道另一侧的实体(通常是一个文件或套接字)之间有效地传输数据。

 

通道与操作系统的文件描述符和文件句柄有着一对一的关系。

 

缓冲区是通道内部用来发送和接收数据的端点



 

 InterruptibleChannel是一个标记接口,当通道使用时可以标示该通道是可以中断的。

通道只能在字节缓冲区上操作。

描述通道行为的接口都是在java.nio.channels包中定义的,不过具体的通道实现却都是从java.nio,channels.spi包中定义的。

 SPI包允许新通道实现以一种受控且模块化的方式被植入到java虚拟机上。

I/O可以分为广义的两大类别:File I/O和Stream I/O。对应文件和套接字。

 FileChannel对象只能通过一个打开的RandomAccessFile、FileInputStream或FileOutputStream对象上调用getChannel()方法来获取。不能直接创建FileChannle对象。

 通道不能重复利用

 

如果一个线程在一个通道上被阻塞并且同时被中断(由调用该被阻塞线程的interrupt()方法的另一个线程中断),那么该通道将被关闭,该被阻塞线程也会产生一个ClosedByInterruptException异常。

假如一个线程的中断状态被设置,并且该线程试图访问一个通道,那么这个通道将立即被关闭,同时抛出ClosedByInterruptException异常。

线程中断状态通过调用Thread.interrupted()方法清除。

 

可以中断的通道也是可以异步关闭的。实现InterruptibleChannel接口的通道可以在任何时候被关闭。当 通道被关闭时,休眠在该通道上的所有线程都将被唤醒并收到一个AsynchronousCloseException异常。

 

Scatter/Ganther指在多个缓冲区上实现一个简单的I/O操作。顺序抽取write的gather.

 

FileChannel类可以实现常用的read,write以及scatter/gather操作

 文件通道总是阻塞式的,本地磁盘I/O延时很少。

FileChannel对象是线程安全的,多个进程可以在同一个实例上并发调用方法而不会引起任何问题。

FileChannel类保证同一个jvm上所有 实例看到的某个文件的视图均是一致的。

FileChannelRandomAccessFile
read()read()
write()write()
size()length()
position()getFilePointer()
position(long new position)seek()
truncatesetLength
forcegetFD().sync()

 

 新的FileChannel类提供了一个名为map()的方法,该方法可以在一个打开的文件和一个特殊类型的ByteBuffer之间建立一个虚拟内存映射。

FileChannel在调用map()方法会创建一个由磁盘文件支持的虚拟内存映射,并在那块虚拟内存空间外部封装一个MappedByteBuffer对象。

通过内存映射机制来访问一个文件会比使用常规方法读写高效得多,甚至比使用通道的效率都高。原因是不需要做明确的系统调用。

MappedByteBuffer对象的数据元素存储在磁盘上的一个文件中。

 

buffer = fileChannel.map(FileChannel.MapMode.READ_ONLY,100,200);

映射整个文件

buffer = fileChannel.map(FileChannel.MapMode.READ_ONLY,0,fileChannel.size());

 MapMode.READ_ONLY只读,MapMode.WRITE_ONLY可写,MapMode.PRIVATE私有,改映射但不改文件。

一旦映射建立之后将保持有效,直到MappedByteBuffer对象被垃圾收集为止。

MemoryMappedBuffer直接反映它所关联的磁盘文件。它有固定大小。如果映射文件大小变化,那么缓冲区的部分或全部内容都可能无法访问,并将返回未定义的数据或抛出未检查的异常。

 public abstract class MappedByteBuffer extends ByteBuffer{

   public final MappedByteBuffer load();

   public final boolean isLoaded();

   public final MappedByteBuffer force();

}

 

FileChannel的传输channel-to-channel两方法transferFrom,transferTo

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当谈到NIO中的Channel时,有四种主要类型的通道:FileChannel、SocketChannel、ServerSocketChannel和DatagramChannel。这些通道分别用于不同类型的I/O操作。 1. FileChannel(文件通道):用于对文件进行读取和写入操作。可以从文件中读取数据到缓冲区,或将缓冲区中的数据写入文件。 示例代码: ```java try (FileChannel fileChannel = FileChannel.open(Paths.get("example.txt"), StandardOpenOption.READ)) { ByteBuffer buffer = ByteBuffer.allocate(1024); int bytesRead = fileChannel.read(buffer); while (bytesRead != -1) { buffer.flip(); while (buffer.hasRemaining()) { System.out.print((char) buffer.get()); } buffer.clear(); bytesRead = fileChannel.read(buffer); } } catch (IOException e) { e.printStackTrace(); } ``` 2. SocketChannel(套接字通道):用于与远程主机进行网络通信。可以连接到远程服务器并进行数据的读取和写入。 示例代码: ```java try (SocketChannel socketChannel = SocketChannel.open()) { socketChannel.connect(new InetSocketAddress("example.com", 8080)); ByteBuffer buffer = ByteBuffer.allocate(1024); String message = "Hello, server!"; buffer.put(message.getBytes()); buffer.flip(); socketChannel.write(buffer); buffer.clear(); int bytesRead = socketChannel.read(buffer); while (bytesRead != -1) { buffer.flip(); while (buffer.hasRemaining()) { System.out.print((char) buffer.get()); } buffer.clear(); bytesRead = socketChannel.read(buffer); } } catch (IOException e) { e.printStackTrace(); } ``` 3. ServerSocketChannel(服务器套接字通道):用于创建服务器端套接字并监听客户端连接请求。一旦有客户端连接,可以接受连接并创建对应的SocketChannel与客户端进行通信。 示例代码: ```java try (ServerSocketChannel serverSocketChannel = ServerSocketChannel.open()) { serverSocketChannel.bind(new InetSocketAddress(8080)); while (true) { SocketChannel socketChannel = serverSocketChannel.accept(); ByteBuffer buffer = ByteBuffer.allocate(1024); int bytesRead = socketChannel.read(buffer); while (bytesRead != -1) { buffer.flip(); while (buffer.hasRemaining()) { System.out.print((char) buffer.get()); } buffer.clear(); bytesRead = socketChannel.read(buffer); } socketChannel.close(); } } catch (IOException e) { e.printStackTrace(); } ``` 4. DatagramChannel(数据报通道):用于进行UDP协议的数据报式通信。可以发送和接收数据报。 示例代码: ```java try (DatagramChannel datagramChannel = DatagramChannel.open()) { datagramChannel.bind(new InetSocketAddress(8080)); ByteBuffer buffer = ByteBuffer.allocate(1024); InetSocketAddress serverAddress = new InetSocketAddress("example.com", 8080); String message = "Hello, server!"; buffer.put(message.getBytes()); buffer.flip(); datagramChannel.send(buffer, serverAddress); buffer.clear(); datagramChannel.receive(buffer); buffer.flip(); while (buffer.hasRemaining()) { System.out.print((char) buffer.get()); } } catch (IOException e) { e.printStackTrace(); } ``` 这些示例代码展示了如何使用不同类型的Channel进行文件操作、网络通信和数据报传输。根据具体的需求,选择适当的通道类型进行I/O操作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值