通道
来源:互联网 发布:d3.js v4 api 编辑:程序博客网 时间:2024/04/19 20:29
通道(Channel)
Java NIO 的通道类似流,但又有些不同:
- 既可以从通道中读取数据,又可以写数据到通道。但流的读写通常是单向的。
- 通道可以异步的读写。
- 通道中的数据总是要先读到一个 Buffer ,或者总是要从一个 Buffer 中写入。
正如上面所说,从通道读取数据到缓冲区,从缓冲区写入数据到通道。如下图所示:
Channel 本身是一个接口,此接口定义了如下方法:
void close() throws IOException // 关闭此通道boolean isOpen() // 判断此通道是否处于打开状态
Channel 的实现
这些是Java NIO 中最重要的通道实现:
- FileChannel : 从文件中读写数据。
- DatagramChannel : 能通过 UDP 读写网络中的数据。
- SocketChannel : 能通过 TCP 读写网络中的数据。
- ServerSocketChannel : 可以监听新进来的 TCP 连接,像 Web 服务器那样。对每一个新进来的连接都会创建一个 SocketChannel。
FileChannel
FileChannel 是 Channel 的子类,可以进行文件的读/写操作,此类的常用方法如下:
public abstract int read(ByteBuffer dst) throws IOException // 将内容读入到缓冲区public abstract int write(ByteBuffer src) throws IOException // 将内容从缓冲区写入到通道public abstract MappedByteBuffer map(FileChannel.MapMode mode, long position, long size) throws IOException // 将通道的文件区域映射到内存中,同时指定映射模式、文件中的映射文件以及要映射的区域大小如果要使用 FileChannel, 则可以依靠 FileInputStream 或 FileOutputStream 类中的 getChannel() 方法取得输入输出的通道。使用通道写入文本的操作:
String[] info = {"MBYD", "WBJBAQBLCA", "www.pegasus.com", "pegasus"}; // 要输出的数据File file = new File("E://out.txt");FileOutputStream fileOutputStream = null; // 文件输出流fileOutputStream = new FileOutputStream(file);FileChannel fileChannel = null; // 声明输出的通道对象fileChannel = fileOutputStream.getChannel();ByteBuffer byteBuffer = ByteBuffer.allocate(1024); // 开辟缓冲for (int i = 0; i < info.length; i++) {byteBuffer.put(info[i].getBytes()); // 向缓冲中写入数据}byteBuffer.flip(); // 重设缓冲,准备输出fileChannel.write(byteBuffer); // 輸出fileChannel.close();fileOutputStream.close();上面程序使用输出通道将内容全部放到缓冲中,一次性写入到文件中的,实际上 FileChannel 是双向操作,同时可以完成输出和输入数据的功能,下面演示进行读写文件的操作。
File file1 = new File("E://out.txt");File file2 = new File("E://outnote.txt");FileInputStream input = null; // 文件输入流FileOutputStream output = null; // 文件输出流input = new FileInputStream(file1);output = new FileOutputStream(file2);FileChannel fin = null; // 声明输入的通道对象FileChannel fout = null; // 声明输出的通道对象fin = input.getChannel();fout = output.getChannel();ByteBuffer buffer = ByteBuffer.allocate(1024);int temp = 0;while ((temp = fin.read(buffer)) != -1) {buffer.flip();fout.write(buffer);buffer.clear();}fin.close();fout.close();input.close();output.close();
内存映射
内存映射可以把文件映射到内存中,这样文件内的数据就可以用内存读/写指令来访问,而不是用 InputStream 或 OutputStream 这样的 I/O 操作类,采样此种方式读取文件的速度是最快的。
Java中访问文件内容的4种方法:
- RandomAccessFile 随机读取数据,此种访问速度较慢。
- FileInputStream 文件输入流,使用此种方式速度较慢。
- 缓冲读取(如BufferedReader) 使用此种方式访问速度较快。
- 内存映射(MappedByteBuffer) 使用此种方式读取速度较快。
想要将文件映射到内存中,可以使用 FileChannel 类提供的 map() 方法。map() 方法在使用时要指定映射模式,在内存映射中提供了 3 种模式,这 3 中模式分别由 FileChannel 类中的 3 个常量表示:
public static final FileChannel.MapMode READ_ONLY // 只读映射模式。 public static final FileChannel.MapMode READ_WRITE // 读取/写入映射模式。public static final FileChannel.MapMode PRIVATE // 专用(写入时拷贝)映射模式。通过一个读取文件的操作来观察如何使用 MappedByteBuffer 读取硬盘上的文件,以操作上面例子中 out.txt 为例:
File file = new File("E://out.txt");FileInputStream input = new FileInputStream(file);FileChannel fin = input.getChannel();MappedByteBuffer mbb = null; // 聲明文件的內存映射mbb = fin.map(FileChannel.MapMode.READ_ONLY, 0, file.length()); // 将文件映射到内存中byte[] data = new byte[(int) file.length()];int foot = 0;while (mbb.hasRemaining()) {data[foot++] = mbb.get();}System.out.println(new String(data));fin.close();input.close();
文件锁 FileLock
在 java 新 IO 中提供了文件锁的功能,这样当一个线程将文件锁定之后,其它线程是无法操作此文件的。要想进行文件锁定操作,则使用 FileLock 类完成,此类的对象需要依靠 FileChannel 进行实例化操作。 FileChannel 类提供的几个方法取得 FileLock 类的实例化对象:
public final FileLock lock() throws IOException // 获取对此通道的文件的独占锁定public abstract FileLock lock(long position, long size, boolean shared) throws IOException // 获取此通道的文件给定区域上的锁定。public final FileLock tryLock() throws IOException // 试图获取对此通道的文件的独占锁定。 public abstract FileLock tryLock(long position, long size, boolean shared) throws IOException // 试图获取对此通道的文件给定区域的锁定。 并指定锁定位置、锁定大小,属于共享锁定(true)或者独占锁定 (false)文件锁的方式有两种:
- 共享锁 :允许多个线程进行文件的读取操作。
- 独占锁 :只允许一个线程进行文件的读/写操作。
文件锁定之后需要依靠 FileLock 类进行解锁,此类的常用方法:
public final boolean isShared() // 判断此锁定是否为共享的。public final FileChannel channel() // 返回文件通道,此锁定保持在该通道的文件上。public abstract void release() throws IOException // 释放此锁定。 public final long size() // 返回锁定区域的大小,以字节为单位。将上面例子中的 out.txt 锁定。
File file = new File("E://out.txt");FileOutputStream output = new FileOutputStream(file, true);FileChannel fout = output.getChannel();FileLock fileLock = fout.tryLock(); // 试图获得此通道的文件锁if (fileLock != null) {System.out.println(file.getName() + "文件锁定 300 秒!");Thread.sleep(300000);fileLock.release(); // 释放文件锁System.out.println(file.getName() + "文件锁定解除了");}fout.close();output.close();以上程序在运行时将文件进行独占锁定,这样其它线程在锁定的 300 秒内是无法对此文件进行读写操作的。
DatagramChannel
Java NIO 中的 DatagramChannel 是一个能收发 UDP 包的通道。因为 UDP 是无连接的网络协议,所以不能像其他通道那样读取和写入。它发送和接收的是数据包。
public class DatagramChannelSender {public static void main(String[] args) throws IOException {send();}private static void send() throws IOException {DatagramChannel channel = DatagramChannel.open(); // 打开 DatagramChannelByteBuffer buffer = ByteBuffer.wrap("下雨的夜晚很安静".getBytes("utf-8")); // 将 byte 数组包装到缓冲区中,编码方式是 utf-8/*buffer = ByteBuffer.allocate(60);buffer.clear();buffer.put("下雨的夜晚很安静".getBytes("utf-8"));buffer.flip();*/channel.send(buffer, new InetSocketAddress("localhost", 10000));channel.close();}}public class DatagramChannelReveiver {public static void main(String[] args) {try {receive();} catch (Exception e) {e.printStackTrace();}}private static void receive() throws Exception {DatagramChannel channel = DatagramChannel.open();channel.socket().bind(new InetSocketAddress(10000));ByteBuffer buffer = ByteBuffer.allocate(60);while (channel.receive(buffer) == null) {Thread.sleep(1000);}buffer.flip();String recStr = Charset.forName("utf-8").newDecoder().decode(buffer).toString();System.out.println(recStr);channel.close();}}
0 0
- 通道
- 通道
- 通道
- 通道
- stm32DMA通道 ADC通道
- 通道和文件通道
- 建立通道
- Alpha通道
- 通道 Channels
- 阿尔法通道
- 图像通道
- dsa通道
- 图像通道
- 什么是通道
- socket通道
- DMA通道
- 什么是通道
- 图像通道
- Linux磁盘空间
- 插入排序之直接插入排序
- 制作红头文件
- 窗口 视口
- Get Local IP Address and Set in the IP Control
- 通道
- iOS自适应(代码) 简单介绍一下
- EDK之路(一)——GPIO
- 如何关闭 APN 推送?
- 111
- OPENCV3.0 双目立体标定
- iOS 心得三 工作中遇到的相关要点
- 无法在Android Studio中设置断点
- 解决Attempting to badge the application icon but haven't received permission from the user to badge th